feat!: retirer readUnion de la surface publiee, et lire un document par requete ancree

readUnion etait N requetes ancrees plus une politique de lot : une lecture
qui echoue avalee en reponse vide, un document dont on ne detient pas la cle
ecarte au lieu d'etre refuse, un regroupement en sacs de proprietes, et le
filtrage du prefixe reserve. Rien en amont ne repond a cette composition, et
son annotation citait sparql_query -- une citation exacte attachee a une
affirmation fausse. Une composition ne s'aligne pas sur une fonction.

Ce qui reste est ce qu'il y avait dessous : docs.sparqlQuery ancre sur un
document, qui va deja chercher la cle servie par le magasin public -- donc
une reference nue suffit toujours pour lire un document public, sans rien
changer a useShapeQuery. Lire plusieurs documents, c'est cet appel une fois
par document, et la tolerance a une lecture qui echoue revient a l'appelant,
la ou l'amont la laisse : une requete ancree sur un depot que le verifier ne
detient pas rejette.

Cote src, l'unique lecture interne restante devient read-document.ts : un
document, une requete ancree, precedee de l'ouverture du depot -- barriere
que index-deposit consulte pour distinguer une absence d'un depot non
synchronise. Le harnais e2e et l'exemple composent la leur, avec leur catch
visible au point d'appel.

Version majeure : 1.0.0-dev.8.
This commit is contained in:
Sylvain Duchesne
2026-09-21 14:08:05 +02:00
parent 05a0f7b148
commit 0c21adebf2
18 changed files with 659 additions and 516 deletions
@@ -47,7 +47,7 @@ import {
} from "../src/emulated-verifier/inbox-processor";
import { resetOpenedRepos } from "../src/emulated-verifier/open-repo";
import { share } from "../src/surface/inbox";
import { readUnion } from "../src/surface/read-model";
import { readDocumentSubjects } from "../src/surface/read-document";
import { sparqlUpdate } from "../src/surface/docs";
import type { Nuri } from "../src/model/types";
@@ -282,9 +282,10 @@ async function write(doc: Nuri, p: string, o: string): Promise<void> {
await sparqlUpdate(SESSION.sessionId, `INSERT DATA { <${doc}> <${p}> "${o}" }`, doc, "test");
}
/** The values `p` carries in `docs`, as the CURRENT holder reads them. */
async function readValues(docs: Nuri[], p: string): Promise<string[]> {
const subjects = await readUnion(docs);
/** The values `p` carries in `doc`, as the CURRENT holder reads them - one document,
* one anchored query, which is all `readUnion` ever did per entry. */
async function readValues(doc: Nuri, p: string): Promise<string[]> {
const subjects = await readDocumentSubjects(doc);
return subjects.flatMap((s) => s.props[p] ?? []);
}
@@ -335,7 +336,10 @@ test("a deposit is drained for the inbox's OWNER, while the depositor still hold
// connected, Alice would now hold a capability nobody gave her.
expect(getCurrentUser()).toBe("alice");
expect(caps.capForHolder("alice", carolDoc)).toBeUndefined();
expect(await readValues([carolDoc], SECRET)).toEqual([]);
// …and the read says so out loud. It used to answer `[]`, because `readUnion` dropped a
// document it could not attempt; the anchored read refuses it instead, which asserts the
// same fact more strongly - Alice is not merely shown nothing, she is told no.
await expect(readValues(carolDoc, SECRET)).rejects.toThrow(/does not hold this document/i);
expect(await linksFiledFor("alice")).toEqual([]);
// …and both Links landed in Bob's space instead.
@@ -371,7 +375,7 @@ test("what the drain filed for the owner is DURABLE: he restores it with his inb
expect(getCaps().capFor(aliceDoc)).toBeUndefined(); // he holds nothing yet
await connectedUser();
expect(getCaps().capFor(aliceDoc)).toBeDefined();
expect(await readValues([aliceDoc], SECRET)).toEqual(["the-protected-content"]);
expect(await readValues(aliceDoc, SECRET)).toEqual(["the-protected-content"]);
});
// --- coalescing --------------------------------------------------------------
@@ -525,7 +529,6 @@ test("nothing about the deferred service reaches the published surface", () => {
"initNg",
"insertObject",
"ng",
"readUnion",
"storeRegistry",
"subscribeDoc",
"subscribeDocs",