fix: une connexion qui échoue ne se résout plus comme une réussite
connectedUser() restaure les capacités reçues et draine les inbox. Aucun de ses chemins ne pouvait échouer : un broker injoignable rendait exactement la même promesse qu'un succès complet. L'application affichait alors des listes vides, et rien nulle part ne disait que la restauration n'avait pas eu lieu. L'énumération m'avait échappé sur deux points, l'agent les a établis. resolveAccount attrapait tout et rendait null : une lecture qui ÉCHOUAIT ressortait donc comme « ce compte n'existe pas ». L'échec était déguisé en absence — c'est la racine du partage cassé trouvé ce matin, dont on n'avait traité que le déclencheur. lookupAccount le remplace : le silence n'est plus possible que sur une absence VÉRIFIÉE. Et readLinks comme readInboxCapPairs avalaient leur propre erreur en rendant un tableau vide, un étage sous le catch de connect. Une panne n'y parvenait même pas. Elles relèvent désormais. La règle est simple : tout échec remonte, seul « il n'y avait rien à faire » se résout en silence. Ce qui reste silencieux — aucun détenteur, compte réellement absent, identité changée en route — l'est parce que c'est la vérité. Le piège consigné hier est fermé par là même : une exécution qui ne peut pas répondre rejette, et ceux qui la rejoignent en héritent. Sa feuille est supprimée, la question qu'elle laissait ouverte étant tranchée. Trois fixtures de test utilisaient un ng vide — une forme qu'aucune plateforme ne présente, dont le TypeError était mangé par le catch. Remplacées par un broker au portefeuille vide. Aucune assertion modifiée.
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
# Doc-debt — app-contract
|
||||
|
||||
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
|
||||
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
|
||||
|
||||
## Raw markers (consolidate into blocks, then delete)
|
||||
- TOUCHED packages/polyfill/src/surface/lifecycle.ts @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
- TOUCHED docs/api-contract.md @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
@@ -1,10 +0,0 @@
|
||||
# Doc-debt — sign-in
|
||||
|
||||
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
|
||||
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
|
||||
|
||||
## Raw markers (consolidate into blocks, then delete)
|
||||
- TOUCHED packages/polyfill/src/shared-wallet/bootstrap.ts @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
- TOUCHED packages/polyfill/src/shared-wallet/access-gate.ts @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
- TOUCHED packages/polyfill/src/surface/lifecycle.ts @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
- TOUCHED packages/polyfill/src/shared-wallet/session.ts @2026-08-13 (session f93872b5-293a-4916-a353-181409a96d42)
|
||||
@@ -29,4 +29,3 @@ The whole thing is scaffolding: upstream, a person opens **their** wallet, it co
|
||||
|
||||
- `knowledge_how-a-user-gets-in` — the flow end to end, and which layer owns each step.
|
||||
- `knowledge_settling-is-not-connecting` — the split, and the cycle that forces it.
|
||||
- `caveat_connect-memoizes-an-abandoned-run` — a live trap, unfixed.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
type: caveat
|
||||
summary: A connection attempt that finds no account returns silently and leaves its abandoned run joinable, so a later legitimate attempt does nothing
|
||||
last_checked: 2026-08-11
|
||||
---
|
||||
|
||||
# A connection run that gives up stays joinable
|
||||
|
||||
In `emulated-verifier/connect.ts`, a connection attempt that finds no account for the acting identity **returns silently** — no restore, no drain — and it has already registered itself as the in-flight run for that identity. Any concurrent caller joins that run and resolves having done nothing.
|
||||
|
||||
That is exactly how sharing broke once (see `knowledge_settling-is-not-connecting`): the trigger was fixed, this mechanism was not.
|
||||
|
||||
**It is still live.** Any future caller that starts connecting before its session can answer will reproduce the same silence: work skipped, promise resolved, no error anywhere. The trap is documented on the setter that fires the connection, but a comment is not a mechanism — nothing prevents it.
|
||||
|
||||
Two things make it nasty: giving up is indistinguishable from succeeding at the call site, and the memoization spreads the damage to callers that did nothing wrong.
|
||||
|
||||
To validate the state of this: look at what the connection routine does when the account lookup answers nothing, and at whether the in-flight registration happens before or after that decision.
|
||||
|
||||
Fixing it properly means deciding what an attempt that cannot answer should be — a failure, a retry, or something never memoized — and that decision has its own blast radius, which is why it was deliberately left out of the fix that closed the symptom.
|
||||
Reference in New Issue
Block a user