diff --git a/packages/client/src/inbox.ts b/packages/client/src/inbox.ts index 9f0ba93..7cb4698 100644 --- a/packages/client/src/inbox.ts +++ b/packages/client/src/inbox.ts @@ -26,6 +26,7 @@ import { sparqlUpdate, sparqlQuery } from "./docs"; import { subscribeDoc } from "./subscribe"; +import { ensureRepoOpen } from "./open-repo"; import { getCurrentUser, getStoreRegistryDeps } from "./polyfill"; import { escapeLiteral } from "./sparql"; import type { Nuri, PrincipalId } from "./types"; @@ -195,6 +196,31 @@ export async function read(targetInbox: Nuri): Promise { /** Alias for {@link read} — the name that reads as "process the inbox now". */ export const materialize = read; +/** + * COLD, BARRIER-GATED read of `targetInbox` — the reliable "process the inbox at + * (re)connection" read. Opens/subscribes the inbox repo and AWAITS its first + * `State` (the deterministic sync barrier — after it, presence is guaranteed and + * absence definitive, {@link ensureRepoOpen}) BEFORE the anchored {@link read}. + * + * Why this over a plain {@link read}: on a FRESH session over the persistent + * wallet (a (re)connection / new page), the inbox repo is not yet in the verifier's + * `self.repos`, so a plain anchored `read` resolves an unopened repo and silently + * returns 0 deposits — even for a deposit a remote session already synced to the + * broker. Gating on the sync barrier makes the read see the synced deposits. This + * is the SAME cold-read heal `discovery.readIndex` applies to the index inbox. + * + * NOT for the `watch` path: {@link watch} already holds the repo open via its own + * `subscribeDoc`, so opening a second bootstrap subscription from inside a watch + * re-read would be redundant and could race the watch's own initial-`State` + * delivery. Use this from a COLD reader (materialize-at-connection), like + * `discovery.readIndex` does. Idempotent per session (no polling); a no-op open on + * the unit fake-ng path (no `doc_subscribe`) so `bun test` is unaffected. + */ +export async function readSynced(targetInbox: Nuri): Promise { + await ensureRepoOpen(targetInbox); + return read(targetInbox); +} + /** * Subscription over an inbox — **event-driven, not polled**. Subscribes to the * inbox document via {@link subscribeDoc} (the platform's `doc_subscribe` push):