OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-did-peer / test / labels.test.mjs

92 lines · javascript ref:
// Label cores: a labeler DID's signed labels reach a keyless reader through the announce (member labels,
// hyper-social #80 step 3).
//
// hpp (0.3.128) projects a labeler DID's signed label log into a membrane-labels core and announces
// labelKey/labelLength beside the firehose. A reader — the gateway's lens, behind a DidPeerRouter — must
// open and fully seed that core, follow its appends, and keep the field when IT re-announces (a seeder
// that dropped labelKey would hide the labels from everyone fronting through it). A labelKey that first
// appears on an already-open front is adopted, like a repoKey.
//
// Run: node test/labels.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 b4a from 'b4a'
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, DidPeerRouter } from '../index.js'

const assert = (c, m) => { if (!c) { console.error('FAIL:', m); process.exit(1) } console.log('  ok -', m) }
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
const waitFor = async (fn, ms = 20000) => { const end = Date.now() + ms; while (Date.now() < end) { if (await fn()) return true; await sleep(100) } return false }
const iso = '2026-10-13T00:00:00.000Z'
const id = createAtprotoIdentityFromKey(new Uint8Array(32).fill(6), { handle: 'labeler.test', pdsUrl: 'https://pds.local' })
const testnet = await createTestnet(3)
const dirs = []
const dir = (p) => { const d = mkdtempSync(join(tmpdir(), p)); dirs.push(d); return d }

// The holder: a signed repo + firehose, and a label core holding two blocks.
const hStore = openCorestore(dir('labels-holder-'))
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()
await seq.sequenceCommit(await mgr.applyWrite({ action: 'create', collection: 'app.bsky.feed.post', rkey: '1', record: { $type: 'app.bsky.feed.post', text: 'hi', createdAt: iso } }), { time: iso })
const labels = hStore.get({ name: 'membrane-labels' })
await labels.ready()
await labels.append([b4a.from('label-0'), b4a.from('label-1')])

const holder = new DidPeer(hStore, { did: id.did, verifyKey: id.publicKey })
await holder.provide({ repoKey: repo.core.key, firehoseKey: seq.core.key, labelKey: labels.key })
assert(holder.labels && holder.labels.length === 2, 'provide opens the holder\'s label core')
const hSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
hSwarm.on('connection', (c) => holder.attach(c))
await hSwarm.join(discoveryTopic(id.did), { server: true, client: true }).flushed()

console.log('# a DidPeerRouter reader opens, seeds and follows the label core')
const rStore = openCorestore(dir('labels-reader-'))
const router = new DidPeerRouter(rStore)
const rSwarm = new Hyperswarm({ bootstrap: testnet.bootstrap })
rSwarm.on('connection', (c) => router.onconnection(c))
const told = []
router.onLabels((did, f) => told.push({ did, f }))
router.add(id.did, { verifyKey: id.publicKey, noRepo: true })
await rSwarm.join(discoveryTopic(id.did), { server: true, client: true }).flushed()
const front = await router.front(id.did, { timeout: 20000 })
assert(!!front, 'the reader fronts the DID')
assert(await waitFor(() => front.labels && front.labels.contiguousLength === 2), 'the front holds both labels (fully downloaded)')
assert(b4a.equals(front.labels.key, labels.key), 'the announced core, by key')
assert(told.length === 1 && told[0].did === id.did && told[0].f === front, 'router.onLabels told the consumer once, with the front — a label core is not a firehose event, so a consumer has no other way to learn of it')
await labels.append(b4a.from('label-2'))
assert(await waitFor(() => front.labels.contiguousLength === 3), 'and follows a new label')

console.log('\n# a re-announcing seeder keeps the field')
let sent = null
front.announceVia({ send: (m) => { sent = m } })
assert(sent && sent.labelKey === b4a.toString(labels.key, 'hex'), 'the reader\'s own announce carries labelKey')
assert(sent.labelLength === 3, 'and labelLength')

console.log('\n# a labelKey that first appears on an open front is adopted')
const late = new DidPeer(openCorestore(dir('labels-late-')), { did: id.did, verifyKey: id.publicKey, noRepo: true })
await late.provide({ firehoseKey: seq.core.key })
assert(late.labels === null, 'no labelKey, no label core')
let none = null
late.announceVia({ send: (m) => { none = m } })
assert(none.labelKey === null && none.labelLength === null, 'announced as null (the field exists)')
assert(await late.adoptLabelKey(labels.key) === true, 'adoptLabelKey opens it')
assert(late.labels && b4a.equals(late.labels.key, labels.key), 'bound to the announced key')
assert(await late.adoptLabelKey(labels.key) === false, 'idempotent')
await late.close()

console.log('\nLABELS OK')
await rSwarm.destroy(); await router.close(); await rStore.close()
await hSwarm.destroy(); await holder.close(); await seq.close(); await repo.close(); await hStore.close()
await testnet.destroy()
for (const d of dirs) rmSync(d, { recursive: true, force: true })