mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
fix(publish): flag + log unconfirmed (optimistic) relay publishes
publishEventToRelay optimistically reports success when a relay handle exposes no ok/failed event and isn't thenable (legacy 'seen'-only relays). That made an UNCONFIRMED publish indistinguishable from a real ack, so a note could show 'Published' with nothing actually stored. The result now carries optimistic:true for that path (callers can distinguish it from a confirmed ack) and logs a dev.warn. Behavior is otherwise unchanged (still treated as success for legacy relays). Publish audit #3. Test: tests/nostr-publish-optimistic.test.mjs. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
3d6ffe997b
commit
ac1dcff184
2 files changed
+60
-3
No files matched your search
+11
-3
@@ -68,12 +68,12 @@ export function publishEventToRelay(pool, url, event, options = {}) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let settled = false;
|
||||
const finalize = (success, error = null) => {
|
||||
const finalize = (success, error = null, optimistic = false) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve({ url, success, error });
|
||||
resolve({ url, success, error, optimistic });
|
||||
};
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
@@ -149,8 +149,16 @@ export function publishEventToRelay(pool, url, event, options = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No confirmation channel: the relay handle exposed neither an ok/failed
|
||||
// event nor a thenable. We still optimistically report success for legacy
|
||||
// "seen"-only relays, but mark the result `optimistic` and log it so a
|
||||
// silently-unconfirmed publish is traceable rather than indistinguishable
|
||||
// from a real relay ack (publish audit #3).
|
||||
clearTimeout(timeoutId);
|
||||
finalize(true);
|
||||
devLogger.warn(
|
||||
`[nostrPublish] Optimistic (unconfirmed) publish success for ${url}: relay gave no ok/failed/then signal.`,
|
||||
);
|
||||
finalize(true, null, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Scenario (SCN-publish-optimistic-flag):
|
||||
// publishEventToRelay optimistically reports success when a relay handle gives
|
||||
// no ok/failed/then signal (needed for legacy "seen"-only relays). Previously
|
||||
// such an UNCONFIRMED success was indistinguishable from a real relay ack, so
|
||||
// a note could show "Published" with nothing actually stored (audit #3).
|
||||
// Given a relay handle with no confirmation channel,
|
||||
// Then the result is success:true but flagged optimistic:true;
|
||||
// Given a relay that emits 'ok',
|
||||
// Then the result is success:true and optimistic:false (a real ack).
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { publishEventToRelay } from "../js/nostrPublish.js";
|
||||
|
||||
const EVENT = { id: "evt", kind: 1, content: "x" };
|
||||
|
||||
test("unconfirmed publish (no ok/failed/then) is flagged optimistic", async () => {
|
||||
const pool = { publish: () => undefined }; // no handle at all
|
||||
const result = await publishEventToRelay(pool, "wss://relay.example", EVENT, {
|
||||
timeoutMs: 1000,
|
||||
});
|
||||
assert.equal(result.success, true, "still reports success for legacy relays");
|
||||
assert.equal(result.optimistic, true, "but marks it as unconfirmed");
|
||||
});
|
||||
|
||||
test("a real 'ok' ack is NOT optimistic", async () => {
|
||||
const pool = {
|
||||
publish: () => ({
|
||||
on(ev, handler) {
|
||||
if (ev === "ok") setTimeout(() => handler(), 0);
|
||||
},
|
||||
}),
|
||||
};
|
||||
const result = await publishEventToRelay(pool, "wss://relay.example", EVENT, {
|
||||
timeoutMs: 1000,
|
||||
});
|
||||
assert.equal(result.success, true);
|
||||
assert.equal(result.optimistic, false, "confirmed ack must not be optimistic");
|
||||
});
|
||||
|
||||
test("a thenable publish that resolves is a confirmed (non-optimistic) success", async () => {
|
||||
const pool = { publish: () => Promise.resolve() };
|
||||
const result = await publishEventToRelay(pool, "wss://relay.example", EVENT, {
|
||||
timeoutMs: 1000,
|
||||
});
|
||||
assert.equal(result.success, true);
|
||||
assert.equal(result.optimistic, false);
|
||||
});
|
||||
Reference in new issue
Block a user