Le partage était cassé : Bob n'ouvrait pas le document qu'Alice venait de lui
partager, sans erreur, juste « (illisible) ». Régression introduite en scindant
ensureIdentity().
Chaîne observée aux sondes, pas déduite : settleIdentity() appelait
setCurrentUser, qui déclenche startConnect(), qui va chercher la session via le
thunk getSession de l'application. Or l'exemple appelle init() DEPUIS
L'EXÉCUTEUR qui construit sessionReady — le thunk ne peut donc pas répondre, par
construction. Il lève, resolveAccount rend null, l'exécution est abandonnée sans
restauration ni drainage, mais s'est déjà enregistrée « en vol ». Le
ensureIdentity() suivant rejoint cette exécution morte et se résout sans avoir
rien fait.
Avant la scission, rien n'appelait setCurrentUser pendant l'évaluation du
module : la session existait, l'exécution était saine, et la rejoindre était
sans danger. C'était bien une affaire de moment.
bootstrap.ts scinde le setter : adoptCurrentUser enregistre qui agit,
setCurrentUser reste « enregistrer + connecter » pour tous les autres appelants.
La moitié sans session ne réclame donc plus de session, et se connecter
redevient l'affaire du seul ensureIdentity(), attendu, là où une session existe.
Ce que ça bloque, tracé avant de livrer : une application qui appellerait init()
sans jamais appeler ensureIdentity() n'aurait plus de restauration en arrière-
plan. Aucun appelant de ce genre n'existe, et avant la scission init() était un
passthrough nu qui ne déclenchait rien — c'est une répartition rétablie, pas un
comportement retiré.
Reste connu, non corrigé : connectedUser mémorise toujours une exécution
abandonnée. Le piège est documenté sur setCurrentUser.
@ng-org/web fait déjà la redirection vers le broker — même hôte, même forme,
même test de cadre (dist/ngweb.js). Le polyfill n'a donc rien à réimplémenter
là : ce qui lui revient, c'est la seule chose qu'init() ne peut pas faire, à
savoir mettre ?ng-id= dans window.location.href avant qu'il ne le lise.
rememberIdentity() s'exécute désormais sur les trois chemins — identité posée
par l'appelant, venue du stockage, ou saisie à la barrière. Le cas du stockage
était le silencieux : le paramètre restait absent, l'iframe lisait une identité
vide et provisionnait un second espace virtuel, sans erreur.
L'écriture dans le stockage et celle dans la barre d'adresse sont deux try
indépendants : un stockage qui refuse d'écrire ne doit pas emporter avec lui le
paramètre, qui est le seul à franchir la frontière de partition.
Le contrat retire l'obligation « être ouverte via la redirection du broker » :
elle n'a jamais été celle de l'application. Ni broker, ni iframe, ni redirection
n'y sont plus nommés.
Le nom @ng-eventually/sdk entrait en collision avec le SDK de NextGraph, dont
ce paquet est justement un polyfill. Impossible d'écrire « le SDK » sans lever
l'ambiguïté à chaque phrase — et le contrat publié, lu par une application,
était le pire endroit pour laisser traîner ça.
packages/sdk → packages/polyfill, @ng-eventually/sdk → @ng-eventually/polyfill,
contract_sdk-surface → contract_polyfill-surface, e2e/sdk-entry.ts →
e2e/polyfill-entry.ts, docs/sdk-reference.md → docs/polyfill-reference.md.
Les occurrences de « SDK » qui désignent celui de NextGraph restent intactes,
y compris les chemins dans nextgraph-rs (sdk/js/orm, sdk/js/web). Le tri s'est
fait occurrence par occurrence, pas par substitution.
Le contrat énonce désormais son identité en une phrase : « This package is a
polyfill of NextGraph's SDK. »