OverviewFilesCommitsIssuesDocsReleasesPeers

favela-peer / test / genesis.test.js

64 lines · javascript ref:
// ⛔ Why the feed does NOT use `host.genesis` for admission.
//
// autobee exposes `host.genesis` and its README says "use this to bootstrap the first writer", so
// the obvious move is to delete the feed's own `__founder__` marker and gate self-admission on it.
// That was tried on 2026-09-06 and this test is why it was reverted.
//
// `system.isGenesis()` reads the system bee's head, and the head does not move until the batch
// flushes. So genesis stays TRUE for every node of the batch that admitted the first writer.
//
// The consequence is not theoretical once `optimistic: true` (the stranger doorbell) lets an
// unadmitted device append at all: two devices each appending a self-admission that lands in one
// apply batch would BOTH see genesis and both be admitted. A stranger would have made itself a
// writer on someone else's feed.
//
// `__founder__` does not have this problem, because it is written into the app view through the
// pending overlay and is therefore visible to the very next op in the same batch.
//
// ⇒ `host.genesis` is safe as "has this log ever been written to", NOT as a per-node admission gate.
// Kept as a regression test: if a future autobee makes genesis flip mid-batch, this fails and the
// marker can be revisited.

import test from 'brittle'
import fs from '#node:fs'
import os from '#node:os'
import { join } from '#node:path'
import b4a from 'b4a'
import Corestore from 'corestore'
import Autobee from 'autobee'

const tmp = () => fs.mkdtempSync(join(os.tmpdir(), 'favela-genesis-'))
const enc = (v) => b4a.from(JSON.stringify(v), 'utf8')

test('★ host.genesis does NOT flip mid-batch — this is why __founder__ stays', async (t) => {
  const seen = []

  const db = new Autobee(new Corestore(tmp()), null, {
    async apply (nodes, view, host) {
      for (const node of nodes) {
        const op = JSON.parse(b4a.toString(node.value, 'utf8'))
        // Read per node, never hoisted — that is the property under test.
        seen.push({ op: op.t, genesis: host.genesis })
        if (op.t === 'add-device') host.addWriter(b4a.from(op.device, 'hex'), { isIndexer: true })
      }
      const w = view.write()
      w.tryPut(b4a.from('applied', 'utf8'), b4a.from(String(seen.length), 'utf8'))
      await w.flush()
    }
  })

  await db.ready()
  t.teardown(() => db.close())

  const self = b4a.toString(db.local.key, 'hex')
  // Both ops in ONE append, so they land in one apply batch — the shape that would hide a hoist.
  await db.append([enc({ t: 'add-device', device: self }), enc({ t: 'noop' })])
  await db.update()

  t.is(seen.length, 2, 'both nodes were applied in one batch')
  t.is(seen[0].op, 'add-device')
  t.ok(seen[0].genesis, 'the first node sees genesis — nothing has been admitted yet')
  t.ok(seen[1].genesis,
    'and so does the SECOND node of the same batch, AFTER addWriter — the head has not moved yet')
})