// Phase 1 OFFLINE verify: boot the loser-club hpp swarm-device against the RECOVERED repo (swarm:false),
// confirm it restores the records + signs a commit that VERIFIES against the DID #atproto key (i.e. the
// servable artifact the membrane fronts). Run from hyper-proto-peer with node. Real state untouched (uses
// the scratch recovery).
import './lib/bare-globals.js' // web-global polyfills for Bare — MUST load first
import process from 'bare-process'
import { readFileSync } from 'bare-fs'
import b4a from 'b4a'
import { bootSwarmDevice } from './lib/device-node.js'
import { deviceKeetKeyPair, attestDeviceChain, rootIdentityPublicKey } from 'atproto-room/lib/membership.js'
import { deriveAtprotoKey } from 'atproto-identity'
import { decodeDidKey } from 'atproto-identity/lib/did-key.js'
import { verifyCommit } from 'atproto-repo/lib/commit.js'
import { deserializeEntry } from 'atproto-room/lib/serve-membrane.js'
const VDIR = '/tmp/claude-1000/-storage-projects-code-hypercore-kb/656ea8cd-954c-48f3-8b96-8bc7edd06967/scratchpad/phase1-verify'
const MEMBRANE = 'https://pds.7rnx.net'
const s = JSON.parse(readFileSync(process.env.HOME + '/.config/loser-club/secrets.json'))
const assert = (c, m) => { if (!c) { console.error('FAIL:', m); process.exit(1) } console.log(' ok -', m) }
// the DID #atproto pubkey the membrane verifies signed commits against (test's exact derivation)
const signKey = deriveAtprotoKey(s.rootMnemonic)
const { pubkey } = decodeDidKey(signKey.didKey)
// Build the founder device bundle from the saved secrets. NOT provisionDevice — it re-derives the DID
// WITHOUT loser-club's feedGen/labeler endpoints (genesis-bound → a different DID). We already HAVE the
// did + signingKey; only deviceProof + rootIdentityKey need deriving (both endpoint-INDEPENDENT).
assert(b4a.toString(deriveAtprotoKey(s.rootMnemonic).privateKey, 'hex') === s.signingKey, 'deriveAtprotoKey(rootMnemonic) reproduces the saved signingKey (pubkey corresponds to the DID #atproto key)')
const founderKp = await deviceKeetKeyPair(s.founderDeviceMnemonic)
const deviceProof = b4a.toString(b4a.from(await attestDeviceChain({ rootMnemonic: s.rootMnemonic, devicePublicKey: founderKp.publicKey })), 'hex')
const rootIdentityKey = b4a.toString(await rootIdentityPublicKey(s.rootMnemonic), 'hex')
const bundle = { did: s.did, signingKey: s.signingKey, deviceProof, rootIdentityKey }
// boot the swarm device against the RECOVERED repo — OFFLINE (swarm:false), no auto-sign loop
const node = await bootSwarmDevice({
storage: VDIR + '/repo', deviceMnemonic: s.founderDeviceMnemonic,
did: bundle.did, signingKey: bundle.signingKey, deviceProof: bundle.deviceProof, rootIdentityKey: bundle.rootIdentityKey,
handle: s.handle, pdsUrl: MEMBRANE, swarm: false, signIntervalMs: 0
})
assert(node.did === s.did, 'bootSwarmDevice booted under the recovered DID')
assert(node.sb.base.writable, 'founder device is a WRITER on the recovered statebase (reopened, no fork)')
// the recovered RECORDS survived the swarm-device reopen
const recs = await node.device.repo.listRecords()
const has = (c, r) => recs.some((x) => x.collection === c && x.rkey === r)
assert(has('app.bsky.feed.generator', 'loser-club'), 'recovered feed.generator/loser-club present after boot')
assert(has('app.bsky.labeler.service', 'self'), 'recovered labeler.service/self present after boot')
// SIGN → the servable signed commit (favela-node wrote records but never signed)
await node.device.claimLease()
const h = await node.device.sign()
assert(h && h.rev, 'swarm device signed a commit (rev ' + (h && h.rev) + ')')
// the signed commit in the __commit__ log VERIFIES against the loser-club #atproto key (what the membrane checks)
const log = await node.device.firehoseLog()
assert(log.length >= 1, '__commit__ firehose log has >=1 signed entry (servable to the membrane)')
const sc = deserializeEntry(log[log.length - 1]).signedCommit
assert(verifyCommit(sc, pubkey), 'the signed commit VERIFIES against the loser-club #atproto key (keyless-frontable)')
console.log('\nPHASE 1 OFFLINE OK: recovered repo boots as the founder swarm-device → records restored → signs a commit that verifies against the DID key (servable to the membrane). network:false throughout.')
await node.close()
process.exit(0)