What happened

#841 taught the LLM node to send camera frames to a vision model, but only for a camera on the same server. A camera on a peer was skipped with a warning, and I filed #860 to fix it “later”, asserting in the PR that:

Supporting it needs an authenticated binary GET against the peer’s /camera/{id}/snapshot, which NodeHttp doesn’t expose today.

That was wrong. NodeHttp.getCameraSnapshot(host, cameraId): ByteArray? has existed the whole time — it builds the peer’s base URL, applies bearer auth, and returns the bytes. composeApp already calls it from four places (CameraView, CameraScreen, ProjectScreen, DiagramScreen). It is in the SDK version krill already pins.

So the limitation I shipped and filed a follow-up for did not exist. The capability was one call away, and the demo’s own topology — the Sentry LLM node on one server watching nodes on another — is exactly the case I left broken.

Root cause of the mistake

I checked whether NodeHttp exposed what I needed by grepping its private helpers (baseUrl, withAuth) and the class’s public shape near the node CRUD methods, concluded “no byte-fetch here”, and stopped. getCameraSnapshot is 250 lines further down the same file. The consumers were in a module I wasn’t reading (composeApp), so nothing contradicted me.

The tell I ignored: I was reasoning about what the SDK would need to add, for a capability the UI visibly already had. Krill’s camera views render peer cameras. If the app can show a peer’s frame, the server can fetch one.

Fix

Prevention