signAndPublishEvent (video publish/edit/repost/mirror), rebroadcastEvent, and
revertVideo now use assertAnyRelayAcceptedOrUnconfirmed: when every relay
times out without rejecting, the event was sent and almost always persisted,
so it no longer surfaces as "Failed to share video". Explicit rejections
still throw.
Messaging stays honest at every consumer:
- relay tally carries `unconfirmed` (now attached on edits too);
describePublishOutcome maps 0-accepted+unconfirmed to a WARNING ("sent,
no relay confirmed yet") — never a fake relay count, never a hard error
- edit/revert controllers say "sent, not confirmed yet" when unconfirmed
- deletes stay CONSERVATIVE: "deleted successfully" only when >=1 relay
ACKed a tombstone or kind-5 (anyRelayAcceptedInSummaries); an unconfirmed
revert no longer aborts deleteAllVersions midway, so the kind-5 always runs
Tests: tests/relay-ack-unconfirmed-content.test.mjs (6).
Co-Authored-By: Claude Fable 5 <[email protected]>
Two replaceable-event (NIP-33/kind 30078) lifecycle fixes found auditing
edit/delete/tombstone:
1. created_at monotonicity. Edits and delete tombstones used bare
Date.now(), with no guarantee of being newer than the version they replace.
NIP-01 keeps the highest created_at (ties -> lowest id), so a device clock
that's behind — or a second edit within the same second — left relays
serving the OLD version: edits silently didn't apply, and (worse) deletions
didn't actually remove the video for other clients (the local in-memory
tombstone masked the failure locally). The edit and revert/delete builders
now use max(now, baseEvent.created_at + 1). created_at is threaded through
revertVideo and _softDeleteVersions so the bulk-delete path keeps it too.
2. Legacy tombstone key mismatch. The deletion builder synthesizes
videoRootId = "LEGACY:<pubkey>:<dTag>" for legacy videos, so its tombstone
keyed as "ROOT:LEGACY:..." while the original legacy event (no videoRootId)
keyed as "<pubkey>:<dTag>" — the tombstone never matched the zombie it was
meant to suppress. getActiveKey now treats a "LEGACY:"-prefixed root as
non-distinct and falls through to the pubkey:dTag identity, so both match.
Verified sound and unchanged: d-tag + videoRootId preservation on edit,
ownership/version checks, dual delete (NIP-09 kind-5 + per-d-tag soft-delete),
and the tombstone guard wired across all ingestion paths.
Tests: edit/tombstone created_at is bumped above a future-dated base
(clock-skew) and uses wall-clock for a past base; a legacy deletion shares the
original event's key. Both fixes mutation-verified.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Aligned `README.md`, `AGENTS.md`, and `docs/` with codebase reality.
- Fixed `ReferenceError` in `js/nostr/managers/SignerManager.js`.
- Implemented missing `resolveEventDTag` in `js/nostr/client.js`.
- Updated `SignerManager.js` to support `nostr-tools` v2 `generateSecretKey` and handle `generatePrivateKey` aliasing (returning `Uint8Array`).
- Updated `js/nostr/publishHelpers.js` to support `finalizeEvent` (v2) by converting hex keys to bytes.
- Updated `js/nostr/sessionActor.js` to correctly identify session actor context, allowing authenticated users to publish watch history.
- Fixed `tests/nostr/integration-remote-flow.test.mjs` by ensuring `generateSecretKey` is mocked.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Extracted payload construction logic from `revertVideo` in `js/nostr/client.js` to `buildRevertVideoPayload` in `js/nostr/publishHelpers.js`.
- Moved `resolveStoragePointerValue` from `js/nostr/client.js` to `js/utils/storagePointer.js` to fix circular dependencies and improve code organization.
- Updated imports in `js/nostr/client.js` and `js/nostr/publishHelpers.js`.
- Verified with existing tests.
Co-authored-by: PR0M3TH3AN <[email protected]>
Moves the repeatedly defined HEX64_REGEX constant to a shared utility
module to improve maintainability and consistency. Updates all consumers
to import from the new location.
Signed-off-by: Jules <[email protected]>
Co-authored-by: PR0M3TH3AN <[email protected]>
- Synced `package-lock.json` with `package.json` to resolve `npm ci` failures.
- Updated `nostr-tools` dependencies to resolve conflicts.
- Fixed `SyntaxError` in `tests/nostr-login-permissions.test.mjs` caused by duplicate code.
- Updated `js/nostr/client.js`, `js/nostr/publishHelpers.js`, `js/nostr/adapters/nsecAdapter.js`, `js/nostr/nip46Client.js` to use `hexToBytes` helper when calling `nostr-tools` functions, as v2+ expects `Uint8Array` instead of hex strings.
- Added `hexToBytes` helper in `js/utils/hex.js`.
- Updated tests (`tests/nostr/dm-direct-message-flow.test.mjs`, `tests/nostr-send-direct-message.test.mjs`, `tests/nostr-private-key-signer.test.mjs`, `tests/nostr/nip46Client.test.js`) to use `Uint8Array` for keys where required.
Co-authored-by: PR0M3TH3AN <[email protected]>