Admin list edits worked with a NIP-07 extension but silently failed with nsec and
NIP-46 (Amber). persistNostrState signed with window.nostr.signEvent directly (and
required requestDefaultExtensionPermissions), so non-extension logins threw
"nostr-extension-missing".
Fix: sign with the ACTIVE signer (getActiveSigner() from the registry — extension/nsec/
NIP-46 all expose signEvent), and only run the extension-permission prompt when the
signer is an extension (type extension/nip07). Regression test in
tests/admin-list-store.test.mjs (nsec signer used while window.nostr.signEvent throws).
Also (per maintainer request): raise the file-size lint margins to stop churning on an
arbitrary cap — THRESHOLD 1000→1200 (new files), GROWTH_MARGIN 50→200 (grandfathered).
TODOs added: #42 follow-up audit of every signing path (must use the active signer, not
window.nostr); #43 logged-in profile card at the top of the profile modal (half-on/half-
off); #44 in-modal storage selector + unlock for the upload modal.
Build + lint clean; admin-list suite green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Admin moderation was author/community-level only. Admins (any editor — same gate as
the author blacklist) can now hide a SINGLE offending video.
- Record: a published kind-30000 NIP-51 list under d-tag bitvid:admin:event-blacklist,
carrying blocked event ids as `e` tags (NOTE_TYPES.ADMIN_EVENT_BLACKLIST schema).
Loaded/persisted through the existing admin-list machinery (adminListStore) and cached
like whitelist/blacklist.
- accessControl: eventBlacklist Set + getEventBlacklist/isEventBlacklisted/
addToEventBlacklist/removeFromEventBlacklist (editor-gated; normalizes hex or
nevent/note) + onEventBlacklistChange.
- Render filter already existed (app.blacklistedEventIds, honored by every feed/grid/
search/playback path) but was fed only by the static ADMIN_INITIAL_EVENT_BLACKLIST
config. app._rebuildBlacklistedEventIds() now merges that static base with the dynamic
admin list, and an onEventBlacklistChange listener rebuilds + refreshes grids on change.
- UI: a "Block this video" item in the per-video ⋯ menu (editor-only), handled by
handleBlacklistEventAction (js/ui/moreMenu/blacklistEventAction.js).
Helpers extracted to js/adminEventBlacklistHelpers.js to keep adminListStore /
accessControl / moreMenuController under their size caps. Tests:
tests/admin-event-blacklist.test.mjs (9). Build + lint clean; admin/access/moderation
suites 56/56.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Cold-start fired one kind-30000 REQ per community-blacklist curator
(loadCommunityBlacklistEntries did Promise.all over references, each a
fetchLatestListEvent) — ~28-32 parallel REQs that dominated the login
relay-REQ spike and starved the feed.
A Nostr filter ORs `authors` and `#d`, so all curators collapse into ONE
batched REQ. New js/adminListBatch.js (pure, mutation-tested):
buildBatchedReferenceFilter + selectNewestEventsForReferences (newest per
author:d-tag, discards author×d-tag cross-products) +
fetchBatchedReferenceEvents (routes through the subscription manager's
list — health-gated/timeout-bounded, not raw pool). Helpers extracted to
their own module so adminListStore stays under its size cap.
Best-effort: on batch failure we return nothing and the cached admin
state carries over (readCachedAdminState).
Addresses pre-launch TODO #9 (cold-login REQ storm). Tests + mutation-
verified (newest selection, cross-product discard). 1249/1250 unit
(known UploadModal flake).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
fetchLatestListEvent fetched admin lists via fetchListIncrementally without an
explicit `since`, so it relied on the persisted per-relay lastSeen. Admin lists
are replaceable events with a single current version whose created_at does not
advance, so once lastSeen == that created_at, every later load queries
since=lastSeen+1 and the relay returns nothing — perpetually hiding the current
list and dropping admin lists whenever the local cache is absent.
Pass since: 0 to force a full fetch of the (tiny) current event each time. Other
list callers anchor an explicit since to their own cached state; admin lists
have no comparable per-list timestamp, so always re-fetching current is both
correct and cheap.
Adds tests/nostr/relayBatchFetcherReplaceable.test.mjs documenting the
replaceable-event since-gate at the fetcher boundary: relying on persisted
lastSeen hides the current event; since: 0 returns it.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Update .github/workflows/ci.yml to install firefox for e2e-headless job
- Update js/adminListStore.js to await nostrClient.initPromise if pool is not ready, preventing race conditions during app startup
Co-authored-by: PR0M3TH3AN <[email protected]>
- Add `firefox` to `npx playwright install` in CI workflow to fix headless execution failures.
- Implement 15s safeguard timeout in `js/app.js` for `_initAccessControl` to prevent app hang during startup.
- Add `SHORT_TIMEOUT_MS` (5s) to `fetchLatestListEvent` in `js/adminListStore.js` to prevent indefinite hanging on relay queries.
- Update `tests/admin-list-store.test.mjs` to force dev mode for warning assertions.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Modified `sanitizeAdminState` in `js/adminListStore.js` to ensure whitelisted users are automatically excluded from the blacklist.
- Updated `tests/admin-list-store.test.mjs` to use `throw-community` failure mode in the mock pool, fixing a flaky test case that incorrectly assumed base lists would load when `throw-authors` was active.
- Updated `tests/ui/tag-pill-list.test.mjs` to expect `#` prefixed tags, aligning with recent UI changes.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Update `fetchListIncrementally` in `js/nostr/client.js` to throw an error if all relays fail, preventing empty returns from being interpreted as data loss.
- Update `HashtagPreferencesService`, `UserBlockListManager`, and `SubscriptionsManager` to handle fetch errors gracefully without wiping local state.
- Update `js/nostr/nip07Permissions.js` to use a short timeout (3s) for experimental permission requests, fixing "clunky" login issues while preserving user interaction time for standard login.
- Remove `try/catch` in `adminListStore.js` fetch logic to allow error propagation to the fallback cache logic.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Added `start` script to `package.json` to ensure `npm run build` is executed before serving, preventing 404 errors for `css/tailwind.generated.css`.
- Updated `js/adminListStore.js` to include the super admin pubkey (decoded from `ADMIN_SUPER_NPUB`) in the filter when fetching admin lists. This resolves the warning: `[adminListStore] Cannot use incremental fetch for editors without author.`
- Added `scripts/agent/debug_frontend.py` to diagnose frontend errors using Playwright.
- Verified fixes by running the debug script and confirming warnings are gone.
Implements a `SyncMetadataStore` to persist last-seen timestamps for replaceable lists (Kind 10000, 30000, 30002, 30015).
Adds `fetchListIncrementally` helper to `NostrClient` which performs per-relay `since` queries.
Updates `SubscriptionsManager`, `UserBlockListManager`, `HashtagPreferencesService`, and `adminListStore` to utilize incremental fetching.
Prevents local cache wipes when incremental fetches return empty results (indicating "no updates").
- Fix circular dependency in `js/adminListStore.js` by importing from `js/nostrClientRegistry.js`.
- Update `js/services/hashtagPreferencesService.js` to include legacy kind 30005 in filters.
- Fix JSDOM mocking in `tests/modal-accessibility.test.mjs` (navigator getter) and `UploadModal` selectors.
- Add `getRoot()` to `js/ui/components/UploadModal.js` for API consistency.
- Update `tests/magnet-utils.test.mjs` expectations to reflect removed default tracker.
- Mock `ensureActiveSignerForPubkey` in `tests/moderation/submit-report.test.mjs`.
- Fix mock loader path in `tests/moderation/trust-seeds.test.mjs` to target `trustBootstrap.js`.
- Fix duplicate pointer tags in `js/nostrEventSchemas.js`'s `buildCommentEvent`.
- Update `tests/nostr/comment-events.test.mjs` and `tests/comment-event-builder.test.mjs` to match current code behavior (legacy kinds, unique tags).
- Removed `WATCH_HISTORY_LEGACY_KIND` (30078) support from watch history fetch and config.
- Removed `WATCH_HISTORY_LEGACY_LIST_IDENTIFIERS` from config.
- Removed `LEGACY_EVENTS_STORAGE_KEY` (bitvidEvents) migration logic from client.
- Removed `loadLegacyAdminState` and `LEGACY_STORAGE_KEYS` from admin list store.
- Updated tests to remove references to legacy kinds.