OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-base / test / repo-projection.test.mjs

51 lines · javascript ref:
// PHASE 0 #4 — REPO-FOR-BRIDGE PROJECTION. The bridge's PeerFront.getRepo assembles a CAR from a
// replicated RepoStore + the firehose's signed commit (getRepoFromCommit, which ASSERTS the RepoStore's
// MST root == the commit's data). atproto-base now exposes that RepoStore (repoKey) kept in sync with
// each emitted head, plus getRepo() — so the bridge can serve com.atproto.sync.getRepo from it.

import test from 'brittle'
import { mkdtempSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { deriveAtprotoKey, createAtprotoIdentity } from 'atproto-identity'
import { readCar } from 'atproto-repo/lib/car.js'
import { verifyRepo } from 'atproto-repo'
import { verifyCommit } from 'atproto-repo/lib/commit.js'
import { AtprotoBase } from '../lib/base.js'

const MNEMONIC = 'test test test test test test test test test test test junk'
const ID = createAtprotoIdentity(MNEMONIC, { handle: 'x.7rnx.net', pdsUrl: 'https://pds.7rnx.net' })
const KEY = deriveAtprotoKey(MNEMONIC)
const post = (text) => ({ $type: 'app.bsky.feed.post', text, createdAt: '2026-07-23T00:00:00.000Z', langs: ['en'] })
function mkBase () { const dir = mkdtempSync(join(tmpdir(), 'repo-')); const base = new AtprotoBase({ path: dir, did: ID.did, privateKey: KEY.privateKey, ackInterval: 100 }); return { base, dir, close: async () => { await base.close(); rmSync(dir, { recursive: true, force: true }) } } }
const recCount = async (car) => (await verifyRepo(await readCar(car))).records

test('getRepo(): valid CAR, consistent with the emitted head, reflects create+delete', async (t) => {
  const A = mkBase(); await A.base.ready()
  t.teardown(() => A.close())

  await A.base.putRecord('app.bsky.feed.post', '3a', post('one'))
  await A.base.putRecord('app.bsky.feed.post', '3b', post('two'))
  const w = await A.base.emitFirehose()

  t.ok(A.base.repoKey && A.base.firehoseKey, 'repoKey + firehoseKey exposed for the bridge to replicate')

  const repo = await A.base.getRepo()
  const v = await verifyRepo(await readCar(repo.carBytes))
  t.ok(v.ok, `getRepo CAR is byte-exact (verifyRepo), mismatches=${JSON.stringify(v.mismatches)}`)
  t.is(v.records, 2, 'both records in the served repo')
  t.is(repo.commitCid.toString(), w.commitCid.toString(), 'getRepo commit == the emitted firehose head (RepoStore stays consistent with the commit)')
  t.ok(verifyCommit(w.signedCommit, KEY.publicKey), 'the served commit verifies against the #atproto key')

  await A.base.delRecord('app.bsky.feed.post', '3a')
  await A.base.emitFirehose()
  t.is(await recCount((await A.base.getRepo()).carBytes), 1, 'delete is reflected in the served repo')
})

test('getRepo(): throws before any commit is emitted', async (t) => {
  const A = mkBase(); await A.base.ready()
  t.teardown(() => A.close())
  await A.base.putRecord('app.bsky.feed.post', '3a', post('one'))
  await t.exception(() => A.base.getRepo(), 'getRepo before emitFirehose throws (no commit to anchor the CAR)')
})