| … | … | @@ -64,6 +64,17 @@ export async function serveDeviceUds (device, { uds, blobs = null, onRelease = n |
| 64 | 64 | // into a fresh line). Public (UDS is filesystem-owner-gated). Bytes as hex, matching get-blob. |
| 65 | 65 | svc.handle('get-repo-car', async () => { const r = await device.exportCar(); return { car: b4a.toString(r.carBytes, 'hex'), commitCid: r.commitCid, dataCid: r.dataCid, rev: r.rev, recordCount: r.recordCount } }) |
| 66 | 66 | svc.handle('apply-write', async (ctx, op) => device.applyWrite(op)) |
| 67 | // get-record: read ONE record back. get-state lists {collection, rkey} and no values, so a client |
| 68 | // could see THAT a record exists and never what it says — which makes "is what I would write |
| 69 | // already there?" unanswerable, and the only alternative is a local fingerprint that drifts from |
| 70 | // the repo. A projector reconciling desired-against-actual needs the actual. |
| 71 | // |
| 72 | // Read-only and UDS-gated like the diagnostics beside it. Returns null rather than throwing for an |
| 73 | // absent record: "not written yet" is an ordinary state for a caller deciding whether to write. |
| 74 | svc.handle('get-record', async (ctx, { collection, rkey } = {}) => { |
| 75 | if (!collection || !rkey) throw new Error('get-record: collection and rkey required') |
| 76 | try { return (await device.repo.getRecord(collection, rkey)) || null } catch { return null } |
| 77 | }) |
| 67 | 78 | // reconcile-bytes: ATTEMPT to pull the authoritative bytes for every converged pointer this node |
| 68 | 79 | // cannot resolve. The daemon already runs this on a loop; exposing it gives an operator a way to |
| 69 | 80 | // demand one NOW and read the result, which is what makes "is this record recoverable?" answerable. |