// favela labeler feed — the full pipeline: Labeler signs labels into a hypercore feed; readLabelFeed
// decodes + VERIFIES each against the labeler's did:key and stores the valid ones; a tampered label is
// rejected; negation over the feed retracts. (The network hop is standard hypercore replication;
// here the reader consumes the feed core directly.) Run: `bare test/labeler.test.mjs`
import '../lib/bare-globals.js'
import { storeDir } from './_store-dir.mjs'
import Corestore from 'corestore'
import { Labeler, readLabelFeed } from '../lib/labeler.js'
import { LabelStore } from '../lib/labels.js'
import { encodeLabel } from 'atproto-identity/lib/labels.js'
const assert = (cond, msg) => { if (!cond) throw new Error('FAIL: ' + msg); console.log(' ok -', msg) }
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
async function waitFor (fn, ms = 5000) { const end = Date.now() + ms; while (Date.now() < end) { if (await fn()) return true; await sleep(50) } return false }
const dir = storeDir('labeler-test')
const store = new Corestore(dir)
const labeler = await new Labeler(store, { privateKey: new Uint8Array(32).fill(7), src: 'did:plc:mod' }).ready()
const URI = 'at://did:plc:a/app.bsky.feed.post/1'
const URI2 = 'at://did:plc:a/app.bsky.feed.post/2'
const l1 = await labeler.label(URI, 'spam', { cts: '2026-07-01T00:00:00.000Z' })
await labeler.label(URI2, 'nsfw', { cts: '2026-07-01T00:00:00.000Z' })
assert(l1.sig && l1.sig.length === 64, 'labeler signs labels (64-byte sig)')
const ls = await new LabelStore(store, { name: 'consumed-labels' }).ready()
const stop = readLabelFeed(labeler.core, labeler.didKey, ls, { onError: (e) => console.error(' [reader]', e.message) })
assert(await waitFor(async () => (await ls.getLabels(URI)).length > 0), 'reader consumed the feed')
assert((await ls.getLabels(URI)).some((l) => l.val === 'spam'), 'spam label on URI (signature verified)')
assert((await ls.getLabels(URI2)).some((l) => l.val === 'nsfw'), 'nsfw label on URI2 (signature verified)')
// tampered label: l1's sig with a changed uri -> verification fails -> NOT stored
await labeler.core.append(encodeLabel({ ...l1, uri: 'at://did:plc:evil/app.bsky.feed.post/1' }))
await sleep(400)
assert((await ls.getLabels('at://did:plc:evil/app.bsky.feed.post/1')).length === 0, 'tampered label (bad sig) is REJECTED, not stored')
// negation over the feed retracts the spam label
await labeler.label(URI, 'spam', { neg: true, cts: '2026-07-05T00:00:00.000Z' })
assert(await waitFor(async () => !(await ls.getLabels(URI)).some((l) => l.val === 'spam')), 'negation over the feed retracts the label')
console.log('\nLABELER OK: sign -> feed -> read -> verify -> store; tampered rejected; negation retracts')
stop()
await labeler.close()
await ls.close()
try { await store.close() } catch {}