@orangecheck/chat-core 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orangecheck/chat-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Verify OC Chat's public artifacts: channel descriptors and posts, directory listings and did:oc session devices. See https://github.com/orangecheck/oc-chat-protocol.",
5
5
  "keywords": [
6
6
  "bitcoin",
@@ -337,6 +337,25 @@ describe('readChannelVersions: "no newer version" only when every read met the f
337
337
  });
338
338
  });
339
339
 
340
+ describe('readChannelVersions: a page it cannot read past is a cut-off read (§8.3.1)', () => {
341
+ const ev = version(founderKey, genesis);
342
+ // 600 events under the channel's tag in one second, newer than the genesis: a
343
+ // page with \`until\` at that second brings back the same 500 every time.
344
+ const junk = Array.from({ length: 600 }, (_, i) => ({ ...ev, id: `junk-${i}`, created_at: ev.created_at + 86400, content: 'x' }));
345
+ const query = async (f: Record<string, unknown>) => {
346
+ const tagged = f['#t'] ? [...junk, ev].filter((e) => f.until === undefined || e.created_at <= (f.until as number)).slice(0, (f.limit as number) ?? Infinity) : [];
347
+ const byKey = Array.isArray(f.authors) && f.authors.includes(ev.pubkey) ? [ev] : [];
348
+ return { events: [...tagged, ...byKey], relayStatus: [{ eose: true }, { eose: true }, { eose: true }, { eose: true }] };
349
+ };
350
+ const keys = async () => ({ keys: [founderKey.nostrPk], answered: true, floor: true });
351
+
352
+ it('600 events in one second stall the open read: it is truncated, not complete', async () => {
353
+ const r = await readChannelVersions(genesis.channel_id, { query, everBoundKeys: keys }, FOUNDER);
354
+ expect(r.events.map((e) => e.id)).toContain(ev.id);
355
+ expect(r.truncated).toBe(true);
356
+ });
357
+ });
358
+
340
359
  describe('recordReads.liveness for an address binding with a relay that did not answer', () => {
341
360
  const ADDR = 'bc1qmr7qn2t0ahj56ztpdswt54kn2r863ukd8wadj8';
342
361
  const kp = generateDeviceKey();
package/src/channel.ts CHANGED
@@ -979,9 +979,13 @@ export async function readChannelVersions(
979
979
  });
980
980
  const fresh = add(res);
981
981
  for (const e of res.events ?? []) until = Math.min(until ?? Infinity, e.created_at);
982
- // A full page that brought something new may have more behind it.
983
- if ((res.events ?? []).length < VERSION_PAGE_LIMIT || fresh === 0) break;
984
- if (page === VERSION_MAX_PAGES - 1) truncated = true;
982
+ // A full page may have more behind it. One that brought nothing new is
983
+ // stuck on a second it cannot page past: the read stops there, cut off.
984
+ if ((res.events ?? []).length < VERSION_PAGE_LIMIT) break;
985
+ if (fresh === 0 || page === VERSION_MAX_PAGES - 1) {
986
+ truncated = true;
987
+ break;
988
+ }
985
989
  }
986
990
  add(await legacy);
987
991