// The blob store a booted node REPORTS must be the one it actually has.
//
// ⛔ THE DEFECT. `blobStore` is hoisted (the reconcile runner needs it) and was assigned ONLY inside
// `if (storeBackend === 'overlay' && repoRoot && recordOverlay)`. Every other consumer takes `blobs`
// straight from that scope, so serveDevice, serveMembrane and the UDS surface all had a working store
// — while the object bootSwarmDevice RETURNS carried `blobs: null` for any DID without the overlay
// backend. favela-host mints DIDs and sets no storeBackend, so that is every DID it has ever made.
//
// ⚠ AND IT ONLY BITES AN IN-PROCESS CONSUMER, which is exactly why it survived: the returned field
// exists FOR the in-process case (the note beside the return says so, naming favela-android), and that
// is the single case it got wrong. Every socket path reads the other variable.
//
// Measured on a handset: 11 posts published to its atproto repo, NONE carrying an image, while the
// same posts reached the fediverse with their jpegs attached — that projection never asks this object
// for a blob store. `upload-blob` threw 'this node has no blob store', BskySink caught it and returned
// null, and each post went out as text with a loss line nobody reads.
//
// ⚠ SOURCE-LEVEL, and deliberately. Observing it otherwise means booting a swarm device with a real
// corestore and overlay — minutes, and network-shaped — to assert one field of the returned object.
// The defect is an ASSIGNMENT IN THE WRONG SCOPE, which is exactly what reading the source can pin.
import test from 'brittle'
import fs from 'bare-fs'
const SRC = new URL('../lib/device-node.js', import.meta.url).pathname
test('the returned blob store is assigned outside the overlay branch', (t) => {
const src = fs.readFileSync(SRC, 'utf8')
t.absent(/blobStore = blobs \/\/ expose to the reconcile runner/.test(src),
'the assignment no longer sits inside the overlay-only branch')
// It must be reached whether or not the branch above ran. The branch closes with `}` on its own
// line; the assignment has to come after it, at the outer indentation.
t.ok(/\n blobStore = blobs\n/.test(src),
'blobStore is assigned at the same level as the `if`, so a legacy DID reports its store too')
// And the two stores are interchangeable by design — the comment in device-node.js says "Same
// drop-in put/get/has API either way" — so reporting the legacy one is correct, not a downgrade.
t.ok(/let blobs = legacyBlobs/.test(src), 'legacy is the default store, and it is a real one')
})
test('nothing else re-narrows it afterwards', (t) => {
const src = fs.readFileSync(SRC, 'utf8')
const assignments = (src.match(/^\s*blobStore = /gm) || [])
t.is(assignments.length, 1, 'exactly one assignment, so there is no second path that can null it')
t.ok(/blobs: blobStore/.test(src), 'and it is still what the node hands back')
})