OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-proto-peer / test / swarm-device-overlay.test.js

81 lines · javascript ref:
// Offline proof of the overlay record backend (SwarmDevice level, no full boot) — the POINTER design
// (Step 2a). With recordStore set, record BYTES materialize as deduped overlay FILES while a tiny
// {$oid,size} POINTER per record lands in the StateBase autobase (so the record set converges
// symmetrically). The firehose #commit still lands on the StateBase; the signed head is byte-identical
// to a full-record StateBase-backed device. Reserved keys are unaffected.

import '../lib/bare-globals.js' // web-global polyfills for Bare (TextEncoder/…) — MUST load first
import test from 'brittle'
import { mkdtempSync, rmSync } from 'bare-fs'
import { join } from 'bare-path'
import os from 'bare-os'
import b4a from 'b4a'
import { SwarmDevice } from '../lib/swarm-device.js'
import { OverlayRepoStore } from 'atproto-store/lib/overlay-repo-store.js'

// Minimal StateBase-shaped KV (get→value|null, list(prefix)→{key:value}) for the reserved __ keys.
class MemKV {
  constructor () { this.m = new Map() }
  async set (k, v) { this.m.set(k, v) }
  async get (k) { return this.m.has(k) ? this.m.get(k) : null }
  async getNow (k) { return this.get(k) }
  async del (k) { this.m.delete(k) }
  async list (prefix = '') { const o = {}; for (const [k, v] of this.m) if (k.startsWith(prefix)) o[k] = v; return o }
  async listNow (prefix = '') { return this.list(prefix) }
}

const DID = 'did:plc:test'
const KEY = (() => { const k = b4a.alloc(32); k[31] = 7; return k })()
const tmp = (t) => { const d = mkdtempSync(join(os.tmpdir(), 'sd-ov-')); t.teardown(() => rmSync(d, { recursive: true, force: true })); return d }
const post = (text, at) => ({ $type: 'app.bsky.feed.post', text, createdAt: at })

test('overlay recordStore: bytes as FILES + tiny POINTERS in the StateBase (symmetric); firehose stays', async (t) => {
  const sb = new MemKV()
  const store = await new OverlayRepoStore(tmp(t)).ready()
  const device = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 'selfkey', firehose: true, recordStore: store })

  await device.putRecord('app.bsky.feed.post', '3kaaa', post('hello', '2026-01-01T00:00:00.000Z'))
  await device.putRecord('app.bsky.feed.post', '3kbbb', post('world', '2026-01-02T00:00:00.000Z'))
  const head = await device.sign({ force: true })

  t.ok(head && head.rev, 'signed a commit')
  t.is((await store.records()).length, 2, 'record BYTES materialized as deduped overlay files')

  const sbMap = await sb.list('')
  const recKeys = Object.keys(sbMap).filter((k) => !k.startsWith('__'))
  t.is(recKeys.length, 2, 'record POINTERS are in the StateBase autobase (symmetric convergence)')
  const ptr = sbMap['app.bsky.feed.post/3kaaa']
  t.ok(ptr && typeof ptr.size === 'number' && ptr.text === undefined, 'the StateBase holds a {$oid,size} pointer, NOT the record bytes')
  t.ok(Object.keys(sbMap).some((k) => k.startsWith('__commit__/')), 'firehose #commit still lands on the StateBase')

  t.is((await device.repo.listRecords()).length, 2, 'listRecords resolves pointers → records transparently')
  await store.close()
})

test('overlay-backed device derives the same MST root as a StateBase-backed device', async (t) => {
  const recs = [
    ['app.bsky.actor.profile', 'self', { $type: 'app.bsky.actor.profile', displayName: 'T' }],
    ['app.bsky.feed.post', '3kaaa', post('hello', '2026-01-01T00:00:00.000Z')]
  ]
  const store = await new OverlayRepoStore(tmp(t)).ready()
  const dOv = new SwarmDevice(new MemKV(), { did: DID, privateKey: KEY, self: 's', firehose: true, recordStore: store })
  for (const [c, r, rec] of recs) await dOv.putRecord(c, r, rec)
  const hOv = await dOv.sign({ force: true })

  const dSb = new SwarmDevice(new MemKV(), { did: DID, privateKey: KEY, self: 's', firehose: true })
  for (const [c, r, rec] of recs) await dSb.putRecord(c, r, rec)
  const hSb = await dSb.sign({ force: true })

  t.is(hOv.dataCid.toString(), hSb.dataCid.toString(), 'same MST root (records converge identically) regardless of backend')
  await store.close()
})

test('default (no recordStore) is unchanged — records go to the StateBase', async (t) => {
  const sb = new MemKV()
  const device = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 's', firehose: true })
  await device.putRecord('app.bsky.feed.post', '3kaaa', post('hi', '2026-01-01T00:00:00.000Z'))
  const keys = Object.keys(await sb.list(''))
  t.ok(keys.includes('app.bsky.feed.post/3kaaa'), 'record stored in the StateBase (legacy default, unchanged)')
  await device.sign({ force: true })
})