fix: à la reconnexion, on retrouve ce qu'on possède — pas seulement ce qu'on a reçu
Une application signalait deux symptômes. Ils sont indépendants, et ils ont une racine commune : se connecter ne rejouait qu'UN des registres durables du portefeuille. connectedUser lisait les AddLink de la branche User — ce qu'on vous a partagé — et rien d'autre. Les capacités des documents que vous avez FAITS vivent sur la branche Store, et un seul chemin les relisait : listMyEntityDocs. Une application qui recharge et va droit à sa note ne tenait donc rien pour elle. Constaté : capFor(note) vaut undefined juste après une connexion résolue, et devient défini dès que listMyEntityDocs passe. Le public survivait en lecture parce que fetchReadCap va rechercher la clé dans le store ; il échouait quand même à l'écriture, qui ne fait pas cette démarche. Deuxième défaut : myInboxes énumérait les inbox sans en remettre la clé au détenteur. Se connecter demandait donc un document qu'on n'avait pas de quoi lire — sur une inbox, que l'application n'a jamais nommée puisque rien ne le lui permet. Troisième défaut, et c'est lui qui rendait tout ça fatal : un drainage refusé faisait échouer toute la connexion. Une inbox n'étant pas consommée par un échec, elle refusait à chaque tentative suivante. D'où le « trois fois sur trois », et d'où un verrouillage plutôt qu'un partage manquant. C'est ma spécification qui l'a créé. En rendant les échecs visibles j'avais écrasé une distinction : ne pas ATTEINDRE la file est une panne, et refuser la session est juste ; ne pas pouvoir APPLIQUER un élément est une donnée, et ça ne doit priver personne de sa session. Le drainage par inbox est désormais isolé — signalé haut et fort, les autres files drainées, la session accordée — tandis qu'énumérer les files et restaurer rejettent toujours. Le parcours e2e ratait les deux : personne ne se reconnecte après avoir ouvert son document aux messages. Il s'arrêtait une reconnexion trop tôt.
This commit is contained in:
@@ -1291,7 +1291,18 @@ export async function listMyEntityDocs(id: string, scope: Scope): Promise<Nuri[]
|
||||
// holder when it runs — so hand the captured key back rather than trust that the
|
||||
// identity has not moved. See `caps.holderKey`.
|
||||
const holderKey = caps.holderKey();
|
||||
for (const cap of await readStoreCaps(store)) caps.learnFor(holderKey, cap);
|
||||
// Tolerant HERE, and only here: `readStoreCaps` propagates (see it, and `readLinks`
|
||||
// beside it), because the connection's restore cannot report success over a read that
|
||||
// never answered. This caller returns the LISTING, which it already has by now, and a
|
||||
// listing without its keys is what it answered before this distinction existed —
|
||||
// unchanged rather than quietly turned into a throw on a published call.
|
||||
let stored: ReadCap[] = [];
|
||||
try {
|
||||
stored = await readStoreCaps(store);
|
||||
} catch (error) {
|
||||
console.error(accessLogPrefix() + " readStoreCaps failed:", error);
|
||||
}
|
||||
for (const cap of stored) caps.learnFor(holderKey, cap);
|
||||
// Which store a document sits in is a registry fact, not one recorded beside the
|
||||
// caps, so it is re-applied here. Marking only — the caps just came from the Store
|
||||
// branch above, and minting a second one beside them is the trap `holdOwnCap` warns
|
||||
|
||||
Reference in New Issue
Block a user