// Personal test-post to the wj62 swarm — run: `bare scripts/wj62-post.mjs "your text here"`
//
// How it works: the swarm devices expose an apply-write RPC (protocol hyper-proto-peer/device/v1,
// lib/serve-device.js) gated by a `writers` allowlist of client Noise pubkeys. This script connects
// over Hyperswarm to a device's control key and submits ONE app.bsky.feed.post. The lease-holder
// (origin) signs it into the shared repo; the bridge fronts it to bsky. bsky limit: 300 graphemes.
//
// The WRITER KEY below is a shared TEST key already in both devices' `writers` allowlist. It is auth,
// not a secret you own — anyone with it can post to wj62. For a real per-user writer, add that user's
// pubkey to the config `writers` and use its seed here.
//
// Optional 2nd arg = which device to submit to (origin|device); default origin. Either works.
import '../lib/bare-globals.js'
import Hyperswarm from 'hyperswarm'
import crypto from 'hypercore-crypto'
import b4a from 'b4a'
import c from 'compact-encoding'
import ProtomuxRPC from 'protomux-rpc'
import { tidNow } from 'atproto-store/lib/tid.js'
// Stable control keys (persistent keypair, hpp >=0.3.2). Verify via the daemon boot log if a device
// was ever reprovisioned: `pgh app log hyper-proto-peer | grep controlKey`.
const CONTROL = {
origin: '8ae330710aaef922dce79a907f6ff8f57e459de61d4d45f1551d5e0ff23a11d7', // stortron
device: 'e0cac0d06e67da9c79674a5ca195809300b04635d1a46254f4fd21edd1ce491d' // tabertron
}
const WRITER_SEED = 'wj62-swarm-test-writer-2026-07-05' // its pubkey is in both devices' writers allowlist
const text = globalThis.Bare.argv[2]
const which = (globalThis.Bare.argv[3] || 'origin').toLowerCase()
if (!text) { console.log('usage: bare scripts/wj62-post.mjs "your text" [origin|device]'); globalThis.Bare.exit(1) }
const ck = CONTROL[which]
if (!ck) { console.log('2nd arg must be origin or device'); globalThis.Bare.exit(1) }
const graphemes = [...text].length
if (graphemes > 300) { console.log('too long: ' + graphemes + ' graphemes (bsky limit 300)'); globalThis.Bare.exit(1) }
const swarm = new Hyperswarm({ keyPair: crypto.keyPair(crypto.hash(b4a.from(WRITER_SEED))) })
// langs: without it bsky's custom-feed tuner (FeedTuner.preferredLangOnly) runs the `lande` detector on
// the text and drops anything it mis-reads as non-English — short/technical posts vanish from the feed on
// bsky.app (but not the author feed or getFeed XRPC). Declaring the language skips detection.
const record = { $type: 'app.bsky.feed.post', text, createdAt: new Date().toISOString(), langs: ['en'] }
const done = new Promise((res, rej) => {
const to = setTimeout(() => rej(new Error('timeout — is the daemon up + this control key current?')), 40000)
swarm.on('connection', async (conn) => {
if (b4a.toString(conn.remotePublicKey, 'hex') !== ck) { conn.destroy(); return }
const rpc = new ProtomuxRPC(conn, { protocol: 'hyper-proto-peer/device/v1', valueEncoding: c.json })
try { const rkey = tidNow(); const r = await rpc.request('apply-write', { action: 'create', collection: 'app.bsky.feed.post', rkey, record }); clearTimeout(to); res({ rkey, r }) } catch (e) { clearTimeout(to); rej(e) }
})
})
swarm.join(b4a.from(ck, 'hex'), { client: true, server: false })
await swarm.flush()
try { const o = await done; console.log('posted to ' + which + ': rkey=' + o.rkey + ' (' + graphemes + ' graphemes) — it will appear on bsky shortly') } catch (e) { console.log('FAILED: ' + e.message) }
await swarm.destroy()