OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / loser-club-cutover.test.js

56 lines · javascript ref:
// loser-club cutover — the multi-DID daemon fully replaces serve-loser-club.mjs: it authors the
// community's app.bsky.feed.generator record on boot AND runs the federation heartbeat (both per-DID
// options folded into bootSwarmDevice). Proves a community DID served by bootMultiDevice federates
// (signed head + live-incrementing heartbeat) with NO bespoke script.
import '../lib/bare-globals.js'
import test from 'brittle'
import fs from 'bare-fs'
import b4a from 'b4a'
import createTestnet from '@hyperswarm/testnet'
import { bootMultiDevice, provisionDevice } from '../lib/device-node.js'
import { deviceKeetKeyPair } from 'atproto-room/lib/membership.js'

const COMMUNITY_ROOT = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art'
const FOUNDER = 'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote'
const tmp = () => { const d = '/tmp/hpp-lcc-' + Math.floor(Math.random() * 1e9); fs.mkdirSync(d, { recursive: true }); return d }
const sleep = (ms) => new Promise(r => setTimeout(r, ms))

test('loser-club cutover: daemon authors feed.generator + runs federation heartbeat (no script)', { timeout: 120000 }, async (t) => {
  const testnet = await createTestnet(3)
  const storage = tmp()
  const dk = await deviceKeetKeyPair(FOUNDER)
  const b = await provisionDevice({ rootMnemonic: COMMUNITY_ROOT, devicePublicKey: dk.publicKey, handle: 'loser-club.local', pdsUrl: 'https://pds.local' })
  const entry = {
    deviceMnemonic: FOUNDER, did: b.did, signingKey: b.signingKey, deviceProof: b.deviceProof, rootIdentityKey: b.rootIdentityKey, handle: 'loser-club.local',
    // the two things serve-loser-club.mjs did, now daemon-owned per-DID options:
    records: [{ collection: 'app.bsky.feed.generator', rkey: 'loser-club', record: { $type: 'app.bsky.feed.generator', did: b.did, displayName: 'loser-club', description: 'the loser-club', createdAt: '2026-07-15T12:00:00.000Z' } }],
    federationHeartbeatMs: 500
  }

  const daemon = await bootMultiDevice({ storage, dids: [entry], swarmOpts: { bootstrap: testnet.bootstrap }, signIntervalMs: 500 })
  t.teardown(async () => { try { await daemon.close() } catch {} ; await testnet.destroy() })

  const node = daemon.byDid.get(b.did)
  t.ok(node && node.sb.base.writable, 'community DID writable (its own founder)')

  // feed.generator record authored on boot
  const gen = await node.device.repo.getRecord('app.bsky.feed.generator', 'loser-club')
  t.ok(gen && gen.displayName === 'loser-club', 'app.bsky.feed.generator record authored on boot')

  // federation heartbeat runs + increments
  await sleep(1500)
  const hb1 = await node.device.repo.getRecord('net.favela.federation', 'self')
  t.ok(hb1 && hb1.seq >= 1, 'federation heartbeat record present')
  await sleep(1400)
  const hb2 = await node.device.repo.getRecord('net.favela.federation', 'self')
  t.ok(hb2.seq > hb1.seq, 'heartbeat seq increments over time (live federation, seq ' + hb1.seq + ' -> ' + hb2.seq + ')')

  // it federates: signed head present, feed.generator in the served set
  const st = await node.device.state()
  t.ok(st.head && st.head.rev, 'signed head present (feed-gen + heartbeat produced #commits)')
  t.ok(st.records.some(r => r.collection === 'app.bsky.feed.generator' && r.rkey === 'loser-club'), 'feed.generator in the served record set')

  // idempotent: the daemon did NOT double-author the feed.generator (single record)
  t.is(st.records.filter(r => r.collection === 'app.bsky.feed.generator').length, 1, 'feed.generator authored exactly once')
})