fix: une liste qu'on ne peut pas ouvrir n'est pas une liste

listMyEntityDocs rendait la liste des documents même quand la lecture des clés
échouait. Vu de l'appelant, une liste dont les documents ne s'ouvrent pas est
INDISCERNABLE d'une liste dont ils s'ouvrent : rien ne signale la différence
jusqu'à une lecture ultérieure qui revient vide, la cause étant alors loin
derrière.

C'était un choix délibéré — ne pas transformer un appel publié en levée, la
liste étant déjà en main à ce moment-là. C'est précisément ce qui en faisait une
demi-vérité plutôt qu'un raccourci. Et c'était le dernier membre connu de la
famille qui a produit une panne chez une application cette semaine.

Les deux lectures sur lesquelles l'appel repose remontent désormais : la branche
Main dit quels documents sont là, la branche Store dit ce qui ouvre chacun. Un
tableau vide signifie donc que ce compte n'a rien créé dans cette portée, et
jamais que le store n'a pas été lu.

readUserStore avalait le même échec pour son propre compte ; son autre appelant,
ownsDocument, garde le comportement actuel par un catch explicite et documenté —
toutes ses réponses étant des refus, il échoue en fermeture, ce qui est la
règle qu'e32b6d0 avait posée.

C'est un changement de comportement d'un appel publié, donc le contrat le dit,
et docs/api-contract.md aussi.

Au passage, deux citations pourries corrigées en citant un SYMBOLE plutôt qu'une
ligne — types.rs:4251 désignait DialogRequest et non Link, index.d.ts:138
désignait const ng et non le type NG. Les douze autres références numériques du
voisinage ont été vérifiées : aucune n'avait bougé.
This commit is contained in:
Sylvain Duchesne
2026-08-17 08:59:34 +02:00
parent 43aadbeb45
commit 90712e0ad0
8 changed files with 228 additions and 44 deletions
+2
View File
@@ -591,6 +591,8 @@ export async function openDocumentInbox(doc: NuriLike): Promise<Nuri>;
// session is RETURNED, never assembled, so no application has a session shape to declare.
```
**`listMyEntityDocs` answers a VERIFIED listing, or it rejects — since 2026-08-17.** It stands on two reads of the store document, and both propagate: the Main branch says which documents are in there, the Store branch says what opens each. Handing back the listing over a key read that never answered was tolerated until then, on the ground that the array was already in hand by that point — which is exactly what made it a half-truth rather than a shortcut, since nothing distinguishes a listing you can open from one you cannot. It is the same `Nuri[]`; the difference shows at the next read, empty, with the cause long gone. It is the ruling the connection path already runs on, applied to the last call that escaped it: **a rejection means "unknown", never "absent"**, and only "there was nothing to do" resolves quietly — so an empty array here means this account created no document in that scope, and never that the store went unread.
### Target — split by what each piece maps to
- **`createEntityDoc(id, scope)` → level 2, VERIFIED direction.** Target: `doc_create(session_id, crdt, class_name, destination, store_repo)` aimed at the identity's real per-scope store (see § 7 for the store-targeting nuance — the nodejs SDK already takes `store_type`/`store_repo` strings). The two writes the lib performs by hand are **native side effects** of `doc_create` upstream: the `ldp:contains` listing on the store's Main branch and the `AddRepo { read_cap }` on its Store branch (`engine/verifier/src/request_processor.rs:697-710`). The `id` parameter is already gone from the published call (2026-08-10); expect `createEntityDoc(scope)` to become `doc_create(sid, …, storeOf(scope))` with no listing/cap bookkeeping.