fix: mon correctif sur createEntityDoc était faux dans les deux sens

Second tour adverse sur le lot C. Six trouvailles, dont trois sur ce que je venais de
livrer.

**Le correctif de `createEntityDoc` reproduisait le défaut qu'il annonçait avoir fermé.**
Il levait sur la PREMIÈRE écriture de registre en échec. Or :

- lever sur le listing sautait l'écriture de la clé — détruisant le chemin de
  récupération que le commentaire d'à côté décrit explicitement (« la clé doit rester
  récupérable même si le listing a échoué »), et laissant le document orphelin ;
- lever sur la clé laissait le document LISTÉ sans clé — précisément l'état « se lit vide
  pour toujours » que je prétendais empêcher, en pire, puisque l'appelant n'a même plus
  sa référence.

Les deux écritures sont désormais tentées, ce qui atterrit reste, et l'échec est rapporté
après en nommant la moitié manquante.

**Le refus de `share` reposait sur une valeur qui confond absence et ignorance.**
`resolveAccount` avale toute erreur de lecture et rend `null`, si bien qu'un incident
réseau faisait répondre « personne ne s'est connecté sous ce nom » à propos de quelqu'un
qui existe. `lookupAccount` propage désormais l'erreur ; `resolveAccount` reste la forme
tolérante que tous les autres appelants veulent.

**J'avais livré ce comportement sans un seul test.** `test/app-surface.test.ts` en ajoute
huit, tous sur ce qu'un APPELANT voit : `ensureIdentity` rend l'identité, un appel de
placement avant connexion nomme l'erreur, le placement agit comme l'utilisateur connecté,
`share` refuse un nom inventé mais laisse remonter une panne, et une création à moitié
écrite échoue en disant quelle moitié — dont le cas « le listing a échoué, la clé est
quand même là ».

En écrivant ces tests j'ai refait dans leur faux la faute que cette revue a corrigée
ailleurs : ignorer le sujet dans la requête de compte, ce qui rendait le dossier d'un
autre utilisateur. Deux des huit échouaient pour cette raison, sans rapport avec le code.

**Et la documentation contredisait le code livré dans le même commit** : le README
enseignait encore `createEntityDoc(me, "protected")` — en JS la portée devient `"alice"` —
et le contrat déclarait `Nuri` là où le code et la feuille disent `NuriLike`.

197 tests unitaires, e2e 40/40 et applicatif 12/12.
This commit is contained in:
Sylvain Duchesne
2026-08-10 10:48:57 +02:00
parent cdc09a1a1d
commit 0d9e2bbe97
5 changed files with 266 additions and 51 deletions
+7 -6
View File
@@ -33,10 +33,10 @@ import {
} from "@ng-eventually/sdk";
configure({ ng: realNg, useShape: realUseShape, getSession, sharedWallet });
await ensureIdentity(); // resolves who I am, and waits for the connection work
const doc = await storeRegistry.createEntityDoc(me, "protected");
await ensureIdentity(); // who I am (returned), connection work awaited
const doc = await storeRegistry.createEntityDoc("protected");
await docs.sparqlUpdate(sid, `INSERT DATA { … }`, doc);
const subjects = await readUnion(await storeRegistry.listMyEntityDocs(me, "protected"));
const subjects = await readUnion(await storeRegistry.listMyEntityDocs("protected"));
```
## Principle — the polyfill compensates, it never extends
@@ -74,8 +74,9 @@ which the e2e suite drives.
```ts
import { storeRegistry, inbox, readUnion } from "@ng-eventually/sdk";
// 1. CREATE — you hold its cap, with nothing to declare.
const doc = await storeRegistry.createEntityDoc(me, "protected");
// 1. CREATE — you hold its cap, with nothing to declare. No identity parameter: a
// session belongs to one user, exactly as the target's own `doc_create` assumes.
const doc = await storeRegistry.createEntityDoc("protected");
// 2. GIVE TO READ — name the document and the person. The key is looked up and
// sealed into a deposit; the recipient applies it by connecting, with nothing
@@ -87,7 +88,7 @@ await inbox.share(doc, "bob");
// PUBLIC store, the store serves its read cap to whoever asks, so the bare
// reference is enough to read it — and if it does not, the reference still names
// it and opens nothing.
const publicDoc = await storeRegistry.createEntityDoc(me, "public");
const publicDoc = await storeRegistry.createEntityDoc("public");
// …put `publicDoc` in a QR code, a message, another document. Nothing else to do.
await readUnion([publicDoc]); // a stranger holding only this reads it
```