OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-did-peer / test / no-repo.test.mjs

65 lines · javascript ref:
// noRepo mode: a DidPeer follows the firehose ONLY (verified head + tail) and does NOT open/replicate the
// repo core — the "one copy" consumer (records come from a shared OverlayRepoStore elsewhere). Proves the
// head still verifies via the firehose, this.repo stays null, and the repo core is never opened.
// Run: node test/no-repo.test.mjs
import { mkdtempSync, rmSync } from 'node:fs'
import { join } from 'node:path'
import { tmpdir } from 'node:os'
import createTestnet from '@hyperswarm/testnet'
import Hyperswarm from 'hyperswarm'
import { RepoStore } from 'atproto-store/lib/repo-store.js'
import { RepoManager } from 'atproto-store/lib/repo-manager.js'
import { FirehoseSequencer } from 'atproto-store/lib/sequencer.js'
import { openCorestore } from 'atproto-store/lib/corestore.js'
import { createAtprotoIdentityFromKey } from 'atproto-identity/lib/atproto-identity.js'
import { discoveryTopic } from 'atproto-identity/lib/discovery.js'
import { DidPeer } from '../index.js'

const assert = (c, m) => { if (!c) { console.error('FAIL:', m); process.exit(1) } console.log('  ok -', m) }
const iso = '2026-07-01T00:00:00.000Z'
const id = createAtprotoIdentityFromKey(new Uint8Array(32).fill(5), { handle: 'norepo.test', pdsUrl: 'https://pds.local' })
const testnet = await createTestnet(3)

// A holder serves a signed repo + firehose.
const hDir = mkdtempSync(join(tmpdir(), 'norepo-holder-'))
const hStore = openCorestore(hDir)
const repo = await new RepoStore(hStore, { name: `atproto-repo:${id.did}` }).ready()
let micros = 1_700_000_000_000_000n
const mgr = await new RepoManager(repo, { did: id.did, privateKey: id.privateKey, clock: () => (micros += 1_000_000n) }).init()
const seq = await new FirehoseSequencer(hStore.get({ name: 'firehose' })).ready()
const w = await mgr.applyWrite({ action: 'create', collection: 'app.bsky.feed.post', rkey: '1', record: { $type: 'app.bsky.feed.post', text: 'hi', createdAt: iso } })
await seq.sequenceCommit(w, { time: iso })
const holder = new DidPeer(hStore, { did: id.did, verifyKey: id.publicKey })
await holder.provide({ repoKey: repo.core.key, firehoseKey: seq.core.key })
const hSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
hSwarm.on('connection', (c) => holder.attach(c))
await hSwarm.join(discoveryTopic(id.did), { server: true, client: false }).flushed()

// A noRepo reader: firehose-only, no repo core.
const rStore = openCorestore(mkdtempSync(join(tmpdir(), 'norepo-reader-')))
const rSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
const reader = new DidPeer(rStore, { did: id.did, verifyKey: id.publicKey, noRepo: true })
rSwarm.on('connection', (c) => reader.attach(c))
await rSwarm.join(discoveryTopic(id.did), { server: false, client: true }).flushed()

const head = await reader.ready({ timeout: 20000 })
assert(!!head, 'noRepo reader reached a VERIFIED head via the firehose (no repo core)')
assert(reader.repo === null, 'repo core was NEVER opened (this.repo === null) — no repo-core replica')
assert(reader.seq && reader.seq.core.length >= 1, 'firehose core IS opened + replicated')
// ⛔ THE SHAPE, NOT THE EMPTINESS, IS WHAT BROKE HERE. 0.2.10 made listRecords return { records, cursor }
// per the lexicon instead of a bare array; this assertion still read `.length` off the wrapper, so it was
// comparing `undefined === 0` and failing on a code path that had never changed behaviour. The noRepo
// contract below is exactly as it always was — zero records, because they live in the consumer's shared
// OverlayRepoStore and not in a repo core this peer never opened.
const listed = await reader.listRecords('app.bsky.feed.post')
assert(Array.isArray(listed.records), 'listRecords returns the lexicon shape { records, cursor }')
assert(listed.records.length === 0, 'and noRepo yields NO records (they come from the shared store, not a repo core)')
assert(listed.cursor === undefined, 'with no cursor — its ABSENCE is how a pager knows to stop')
assert((await reader.getRecord('app.bsky.feed.post', '1')) === null, 'getRecord returns null in noRepo mode')

console.log('\nNO-REPO OK: firehose-only consumer verifies the head + follows the tail with NO repo-core replica')
await rSwarm.destroy(); await reader.close(); await rStore.close()
await hSwarm.destroy(); await holder.close(); await seq.close(); await repo.close(); await hStore.close()
await testnet.destroy()
rmSync(hDir, { recursive: true, force: true })