From 88ce8d17c56ab3c1f309712dcf5e02fbc6f0814a Mon Sep 17 00:00:00 2001 From: Sylvain Duchesne Date: Tue, 15 Sep 2026 15:31:07 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20readUnion=20=C3=A9num=C3=A8re=20par=20c?= =?UTF-8?q?ontrainte=20d'=C3=A9mulation,=20pas=20par=20manque=20de=20la=20?= =?UTF-8?q?cible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/polyfill/src/surface/read-model.ts | 27 ++++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) 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,