OverviewFilesCommitsIssuesDocsReleasesPeers

favela-peer / test / doorbell-peer.test.js

87 lines · javascript ref:
// The receiving half of the doorbell, at the Peer surface.
//
// ⚠ The optimistic append itself is not exercised HERE — that is doorbell-wire.test.js, which since
// 2026-09-15 proves it across a replication pipe. What this file proves is everything the wire
// carries into — that a knock lands as a request, that accepting one follows the knocker
// rather than admitting them, and that nothing about it touches the feed's writer set.

import test from 'brittle'
import fs from '#node:fs'
import os from '#node:os'
import { join } from '#node:path'
import Corestore from 'corestore'
import { RecordStore } from '../lib/record-store.js'
import { Feed } from '../lib/feed-base.js'
import { Peer } from '../lib/peer.js'
import { KNOCKS } from '../lib/feed.js'
import { attest, identity } from './helpers.js'

// ⛔ A knock must prove which identity is knocking (feed.js applyKnock). These tests append it through
// MY writer as a stand-in for a stranger's, so it carries a proof binding that writer to a separate
// identity: the knock is then keyed by that identity's root, and still names THEIR feed.
const KNOCKER_ID = await identity()
const KNOCKER = await KNOCKER_ID.device()
const knockOp = (me, them) => Buffer.from(JSON.stringify({ t: 'knock', feed: them.key.toString('hex'), proof: KNOCKER.bind(me.feed.deviceKey) }), 'utf8')

const tmp = () => fs.mkdtempSync(join(os.tmpdir(), 'favela-bell-'))

async function mkFeed (optimistic = true) {
  const f = new Feed(new Corestore(tmp()), null, { store: new RecordStore(tmp()), optimistic })
  await f.ready()
  await f.addDevice(await attest(f))
  await f.update()
  return f
}

test('a knock appears at the Peer surface and accepting it FOLLOWS, never admits', async (t) => {
  const me = await new Peer(await mkFeed()).ready()
  const them = await mkFeed()
  t.teardown(() => Promise.all([me.close(), them.close()]))

  // ⚠ Appended by MY OWN writer, because there is no transport to carry a stranger's optimistic
  // block. So this exercises the doorbell's HANDLING — where a knock lands, what accepting it does —
  // and not its authorisation. That a stranger may knock and may do nothing else is proven at the
  // unit level in knock.test.js, against a foreign device key.
  await me.feed.base.append(knockOp(me, them))
  await me.update()

  const knocks = await me.knocks()
  t.is(knocks.length, 1, 'the knock is waiting')
  t.is(knocks[0].feed, them.key.toString('hex'))

  const before = await me.feed.devices()
  await me.admitKnock(them.key, them)
  await me.update()

  t.alike(await me.following(), [them.key.toString('hex')], 'accepting means I follow them')
  t.alike(await me.feed.devices(), before, '⛔ and my writer set is unchanged')
  t.alike(await me.knocks(), [], 'the knock is cleared')
})

test('dismissing clears without following', async (t) => {
  const me = await new Peer(await mkFeed()).ready()
  const them = await mkFeed()
  t.teardown(() => Promise.all([me.close(), them.close()]))

  await me.feed.base.append(knockOp(me, them))
  await me.update()
  await me.dismissKnock(them.key)
  await me.update()

  t.alike(await me.knocks(), [], 'gone')
  t.alike(await me.following(), [], 'and not followed')
})

test('knocks never leak into the timeline or the record set', async (t) => {
  const me = await new Peer(await mkFeed()).ready()
  const them = await mkFeed()
  t.teardown(() => Promise.all([me.close(), them.close()]))

  await me.feed.base.append(knockOp(me, them))
  await me.update()

  t.alike(await me.timeline(), [], 'no posts')
  t.alike(await me.feed.list(), [], 'reserved namespaces are not records')
  t.absent((await me.feed.list()).some((r) => r.key.startsWith(KNOCKS)))
})