diff --git a/packages/polyfill/src/surface/read-model.ts b/packages/polyfill/src/surface/read-model.ts index e536a22..27d8541 100644 --- a/packages/polyfill/src/surface/read-model.ts +++ b/packages/polyfill/src/surface/read-model.ts @@ -170,12 +170,31 @@ async function readDoc( * isolation needs a repo per entity), but it is a recommendation about writing: the * read reports what is there. * - * Never an anchorless union-scan over all graphs (which is O(wallet size) and wrong - * on a shared / bloated wallet — the footgun this path exists to avoid). Each doc is - * read with an anchored default-graph query, O(1) per doc, independent of wallet - * size — a non-empty wallet no longer matters. Reads run in parallel via `Promise.all`. + * ── Why this enumerates, and why that is OURS and not the target's ──────── + * Upstream DOES have a query that spans many documents: `resolve_target_for_sparql` + * (`engine/verifier/src/request_processor.rs`) accepts `UserSite` — or no target at + * all — and returns `Ok(None)`, which the verifier itself annotates "QUERYING UNION + * GRAPH". It is refused for updates (`InvalidTarget`) and allowed for reads. So + * "the target cannot read several documents at once" is FALSE, and this path must + * not be read as compensating for a missing upstream capability. + * + * What makes that union unusable HERE is our own emulation: one shared wallet holds + * EVERY virtual identity, so a scan over all graphs crosses identity boundaries that + * upstream does not have (there, a wallet is one person's). The cost argument — + * O(wallet size) — follows from the same artefact. Both reasons are `polyfill-era`. + * + * Each doc is therefore read with an anchored default-graph query, O(1) per doc, + * in parallel via `Promise.all`. + * + * OPEN, and deliberately not settled here: whether enumerating is what an + * application should be taught at all. Targeting `PrivateStore` is a first-class + * option upstream, and whether it reaches a document's CONTENTS — or only the store + * repo's own graph, documents being repos of their own — decides it. Until that is + * established, treat this shape as unconfirmed rather than as the aligned answer. */ // @provenance readUnion kind=aligned level=2 ref=sdk/js/lib-wasm/src/lib.rs:sparql_query — one anchored query per document — upstream's own anchoring (`resolve_target_for_sparql`), composed client-side +// @provenance readUnion.enumeration kind=invention level=none ref=none — upstream offers a union query over many documents (`UserSite`/no target → union graph); enumerating instead is OURS, forced by the shared wallet, and UNCONFIRMED as the shape to teach — see the docstring's open question +// @provenance readUnion.swallow kind=invention level=none ref=none — a failing document is skipped and reads as empty; upstream has no batch read at all, so it has no counterpart for what a partial failure should do export async function readUnion( docsLike: NuriLike[], onUnreadable?: (doc: Nuri, error: unknown) => void,