// feed-holder.test.js — the bridge holds somebody else's feed and reads it.
//
// ⛔ REAL feeds, real replication over a pipe. The unit tests above use a fake held feed, which
// cannot tell me whether an Autobee opened by KEY on a second corestore actually converges — and
// that is the whole claim being made here.
import test from 'brittle'
import fs from 'bare-fs'
import os from 'bare-os'
import { join } from 'bare-path'
import Corestore from 'corestore'
import { Feed } from 'favela-peer/lib/feed-base.js'
import { RecordStore } from 'favela-peer/lib/record-store.js'
import { FavelaFeed } from '../lib/favela-feed.js'
import { attest, identity } from 'favela-peer/test/helpers.js'
const tmp = () => fs.mkdtempSync(join(os.tmpdir(), 'holder-'))
function pipe (a, b) {
const s1 = a.replicate(true)
const s2 = b.replicate(false)
s1.pipe(s2).pipe(s1)
return () => { s1.destroy(); s2.destroy() }
}
async function until (fn, { timeout = 5000 } = {}) {
const deadline = Date.now() + timeout
while (Date.now() < deadline) {
const v = await fn()
if (v) return v
await new Promise((r) => setTimeout(r, 25))
}
return null
}
test('★★ a bridge holding a feed by KEY reads its posts and its reach', async (t) => {
const records = tmp() // stands in for the overlay: the log carries pointers, bytes travel separately
// The peer — somebody else's machine.
const peer = new Feed(new Corestore(tmp()), null, { store: new RecordStore(records) })
await peer.ready()
await peer.addDevice(await attest(peer))
await peer.update()
await peer.put('reach', 'self', { frontmatter: { networks: ['fediverse'], createdAt: 'x' }, body: '' })
await peer.put('post', '01k2test', { frontmatter: { createdAt: '2026-09-08T00:00:00Z' }, body: 'over the swarm\n' })
await peer.update()
// The bridge — a SECOND corestore, opening the same feed BY KEY. It has no credential for it.
const bridge = new Feed(new Corestore(tmp()), peer.key, { store: new RecordStore(records) })
await bridge.ready()
t.teardown(() => Promise.all([peer.close(), bridge.close()]))
const unpipe = pipe(peer.base.corestore ?? peer.base.store, bridge.base.corestore ?? bridge.base.store)
t.teardown(unpipe)
const held = new FavelaFeed({ feed: bridge })
const got = await until(async () => {
const { rows } = await held.ownPosts()
return rows.length ? rows : null
})
t.ok(got, 'the post replicated to a bridge that only had the key')
t.is(got[0].name, '01k2test')
t.is(got[0].body, 'over the swarm\n')
const reach = await held.reach()
t.alike(reach.networks, ['fediverse'], 'and its owner\'s consent came with it')
// ⛔ The bridge cannot write to a feed it merely holds. That is the keyless claim.
t.absent(bridge.base.writable, 'the bridge is NOT a writer on their feed')
})
// ⛔⛔ THE TRIGGER, and it is the reason a registered user's posts reached nobody.
//
// The outbox had all 16 of ashatron's posts and prsm.space saw none of them, because an outbox is a
// PULL surface and no fediverse server backfills one. Delivery needs a push, the push needs
// `Publisher.onHead()`, and nothing ever called it for a held feed: the primary gets `onHead` from
// DidPeer and a favela feed had no equivalent.
//
// ⛔ AND HOOKING ONCE MISSES A WRITER. Measured on this exact setup: the bridge reports ONE writer
// immediately after `ready()` and TWO once replication settles — the second arrives with the system
// core. A snapshot taken at hold() therefore hooks a real core and still misses the one that shows
// up later, which is the failure mode that reads as "it worked in testing". favela-peer paid for
// this shape three separate times (boot-only, then an `update` event that only fires inside
// `_onError`, then a writer-set snapshot), and each version SHIPPED because the unit tests were
// green and only a real append over a real pipe could tell.
//
// So this asserts against real replication: a post written on the peer AFTER the bridge is already
// holding and watching must reach the callback with nothing polling.
test('⛔⛔ watch() fires when a held feed advances — real append, real pipe', async (t) => {
const records = tmp()
const peer = new Feed(new Corestore(tmp()), null, { store: new RecordStore(records) })
await peer.ready()
await peer.addDevice(await attest(peer))
await peer.update()
const bridge = new Feed(new Corestore(tmp()), peer.key, { store: new RecordStore(records) })
await bridge.ready()
t.teardown(() => Promise.all([peer.close(), bridge.close()]))
const unpipe = pipe(peer.base.corestore ?? peer.base.store, bridge.base.corestore ?? bridge.base.store)
t.teardown(unpipe)
// Stand in for the FeedHolder's own storage/swarm — this test is about the trigger, not the swarm.
const { FeedHolder } = await import('../lib/feed-holder.js')
const holder = Object.create(FeedHolder.prototype)
holder._held = new Map([[bridge.key.toString('hex'), { feed: bridge }]])
holder._hooked = new Map()
holder._watchers = new Map()
holder.debounceMs = 50
holder._log = () => {}
let fires = 0
holder.watch(bridge.key, () => { fires++ })
t.teardown(() => { for (const [, w] of holder._watchers) if (w.timer) clearTimeout(w.timer) })
// The boot fire is a real trigger and counts — it is what reconciles a feed held across a restart.
await until(async () => fires >= 1)
const afterBoot = fires
// Now somebody writes, with the bridge already holding. Nothing here polls the feed.
await peer.put('post', '01k2later', { frontmatter: { createdAt: '2026-09-08T01:00:00Z' }, body: 'written after the watch\n' })
await peer.update()
const advanced = await until(async () => (fires > afterBoot ? fires : null), { timeout: 10000 })
t.ok(advanced, 'the watcher fired on a remote append, with nothing polling')
const stats = holder.watchStats()
const one = Object.values(stats)[0]
// ⛔ Counted per trigger so a dead hook is OBSERVABLE. The only evidence favela-peer had for three
// broken versions was how LONG something took, which is inference, not measurement.
t.ok(one.append > 0, 'and it was the APPEND hook that fired, not the boot pass')
t.ok(one.hooked > 0, 'writer cores were hooked — after the feed had them, not before')
// And the post is readable, so the callback is being handed a feed that actually advanced.
const { rows } = await new FavelaFeed({ feed: bridge }).ownPosts()
t.ok(rows.some((r) => r.name === '01k2later'), 'the record the trigger was announcing')
})
// ⛔⛔ A KNOCK MUST NOT STRAND THE BRIDGE BEHIND THE OWNER (2026-10-12).
//
// FeedHolder opened every held feed with favela-peer's default of `optimistic: false`. Every favela
// node opens feeds with `optimistic: true` (favela-peer node.js: "the doorbell is on by default"), and
// the owner's apply ACKS a stranger's knock. So the owner's log links past the knock and a holder that
// refuses optimistic blocks can never follow it: the two compute different views of one log. MEASURED
// live on fleeky's feed: the bridge stuck at 106 of 113 applied, the newest posts never reaching the
// fediverse. (On autobee 2.1.1 the same knock also pinned a core; that half is favela-peer's
// holder-after-knock.test.js.)
//
// So this goes through FeedHolder.hold() itself — the place the option is chosen — and asserts the
// bridge sees what the owner wrote AFTER a stranger knocked.
test('⛔⛔ a knock on a held feed does not strand the bridge behind the owner', async (t) => {
const { FeedHolder } = await import('../lib/feed-holder.js')
const records = tmp()
// The owner, opened the way a favela node opens it.
const owner = new Feed(new Corestore(tmp()), null, { store: new RecordStore(records), optimistic: true })
await owner.ready()
await owner.addDevice(await attest(owner))
await owner.update()
// A stranger knocks from their own machine: a reader of the owner's log, a writer of nothing in it.
const stranger = new Feed(new Corestore(tmp()), null, { store: new RecordStore(tmp()), optimistic: true })
await stranger.ready()
const ownerOnStranger = new Feed(new Corestore(tmp()), owner.key, { store: new RecordStore(records), optimistic: true })
await ownerOnStranger.ready()
const unpipeStranger = pipe(owner, ownerOnStranger)
await until(async () => { await ownerOnStranger.update(); return (await ownerOnStranger.devices()).length > 0 }, { timeout: 10000 })
// A knock proves which identity is knocking (favela-peer feed.js applyKnock): the stranger's device
// binds the writer core it knocks through.
const strangerDevice = await (await identity()).device()
await ownerOnStranger.knock(stranger.key, (writerKeyHex) => strangerDevice.bind(writerKeyHex))
t.ok(await until(async () => { await owner.update(); return (await owner.knocks()).length }, { timeout: 10000 }),
'setup: the stranger\'s knock landed in the owner\'s feed')
await owner.put('post', 'after-knock', { frontmatter: { createdAt: '2026-10-12T00:00:00Z' }, body: 'written after the knock\n' })
await owner.update()
// The bridge holds the owner's feed through FeedHolder, with an inert swarm: replication is piped by
// hand, so this test is about the hold, not the DHT.
const swarm = { connections: [], on () {}, join () {}, async leave () {} }
const holder = new FeedHolder({ storage: tmp(), swarm })
await holder.ready()
const held = await holder.hold(owner.key)
const unpipeBridge = pipe(owner, held.feed)
t.teardown(async () => {
unpipeStranger(); unpipeBridge()
await Promise.all([owner.close(), stranger.close(), ownerOnStranger.close()])
await holder.close()
})
const settles = (p, ms) => Promise.race([p.then(() => true), new Promise((r) => setTimeout(() => r(false), ms))])
const seen = await until(async () => {
if (!(await settles(held.feed.update(), 2000))) return null
return (await held.feed.pointers('post')).some((p) => p.name === 'after-knock') || null
}, { timeout: 15000 })
t.ok(seen, 'the bridge sees what the owner wrote after the knock')
t.absent(held.feed.base.writable && (await held.feed.devices()).includes(held.feed.deviceKey),
'⛔ and holding still grants the bridge nothing on the roster')
})