/**
* resolveRelease's direct-replica path must not depend on a settle TIMER.
*
* 2026-10-11, stortron: the sidecar was wedged (UDS backlog full, EAGAIN), so
* `pgh app update pear-git-v3` fell back to replicating the registry itself,
* slept a fixed 500 ms, and read `latest` from a half-synced view: 0.1.46 (April)
* instead of 0.1.254. Correctness has to come from the replication protocol —
* findingPeers + update({ wait: true }) — not from how long we waited.
* settleMs: 0 makes the old timer-dependence deterministic.
*/
import test from 'brittle'
import fs from '#node:fs'
import path from '#node:path'
import os from '#node:os'
import Corestore from 'corestore'
import Hyperswarm from 'hyperswarm'
import createTestnet from 'hyperdht/testnet'
import { ReleaseRegistry } from '../lib/release-registry.js'
import { resolveRelease } from '../lib/resolve-release.js'
const tmp = (p) => fs.mkdtempSync(path.join(os.tmpdir(), p + '-'))
async function publisher (t, bootstrap, versions) {
const store = new Corestore(tmp('pub-store'))
const registry = new ReleaseRegistry(store)
await registry.ready()
for (const [version, publishedAt] of versions) {
await registry.add({ name: 'app', version, publishedAt, treeHash: 'f'.repeat(64) })
}
const swarm = new Hyperswarm({ bootstrap })
swarm.on('connection', (c) => store.replicate(c))
swarm.join(registry._base.discoveryKey, { server: true, client: false })
await swarm.flush()
t.teardown(async () => { await swarm.destroy(); await registry.close(); await store.close() })
return registry
}
test('cold direct replica resolves the NEWEST release with no settle time', async (t) => {
const testnet = await createTestnet(3)
t.teardown(() => testnet.destroy())
const versions = []
for (let i = 1; i <= 40; i++) versions.push(['0.1.' + i, new Date(Date.UTC(2026, 0, i)).toISOString()])
const reg = await publisher(t, testnet.bootstrap, versions)
const { entry, via, cleanup } = await resolveRelease({
registryKeyHex: reg.keyHex,
name: 'app',
preferSidecar: false,
settleMs: 0,
storeDir: tmp('cold-replica'),
bootstrap: testnet.bootstrap
})
await cleanup()
t.is(via, 'replica')
t.is(entry && entry.version, '0.1.40', 'latest is the newest published, not whatever had arrived')
})
test('no peer at all: resolves null once discovery ends (no hang, no timer)', async (t) => {
const testnet = await createTestnet(3)
t.teardown(() => testnet.destroy())
const lonely = new Corestore(tmp('lonely'))
const reg = new ReleaseRegistry(lonely)
await reg.ready()
const key = reg.keyHex
await reg.close(); await lonely.close()
const { entry, cleanup } = await resolveRelease({
registryKeyHex: key,
name: 'app',
preferSidecar: false,
storeDir: tmp('cold-replica-2'),
bootstrap: testnet.bootstrap
})
await cleanup()
t.is(entry, null)
})
test('isOlderVersion — numeric dotted compare; null when not comparable', async (t) => {
const { isOlderVersion } = await import('../lib/resolve-release.js')
t.is(isOlderVersion('0.1.46', '0.1.254'), true, 'the stortron case')
t.is(isOlderVersion('0.1.254', '0.1.251'), false)
t.is(isOlderVersion('0.1.254', '0.1.254'), false, 'same is not older')
t.is(isOlderVersion('0.1431.0', '0.1429.0'), false)
t.is(isOlderVersion('1.0', '0.9.9'), false, 'missing segment = 0')
t.is(isOlderVersion('master-ed31de1', '0.1.1'), null, 'non-numeric: no opinion')
t.is(isOlderVersion('0.1.5', undefined), null)
})