Le harnais e2e parlait à un sac de méthodes posé sur `window.__sdk`. Il prouvait
que les fonctions s'exécutaient, jamais qu'on pouvait écrire une application avec
— et cet écart a livré un vrai défaut : l'inbox d'un document était verte en test
et inutilisable en vrai, parce que le harnais faisait traverser une adresse d'une
identité à l'autre par une variable, ce qu'aucune application ne peut faire.
`examples/notebook` est une application minimale en DOM natif, qui résout
`@ng-eventually/client` comme un consommateur externe (workspace, dépendance
déclarée, aucun import privilégié). Elle ne peut faire que ce qu'une application
peut faire.
Elle s'est déjà payée deux fois pendant son écriture :
- `UnionSubject.subject` et `.graph` étaient typés `string` alors que ce sont
toujours des références de document. Un consommateur devait donc caster ce
qu'il venait de lire avant de le repasser — un cast à cet endroit précis
rouvre la confusion que les types template literal existent pour fermer.
- l'écran d'accès normalisait ce que l'utilisateur SAISIT mais pas ce que l'URL
porte, si bien qu'un lien `?ng-id=@Erin` ouvrait un espace différent de celui
de la même personne tapant `erin`. Une seule normalisation désormais, celle
du registre.
Le domaine est volontairement mince — des notes — mais suffit à exercer le
placement par scope, la possession de caps, le partage dirigé, les inbox par
document et la lecture réactive.
170 tests unitaires, typecheck vert sur la lib, l'exemple et le harnais.
Chaque étape de cet écran n'existe que parce qu'un wallet héberge plusieurs
identités. Une app qui l'implémente écrit du code qu'elle devra supprimer, et
pire, du code qui enseigne à ses auteurs un modèle que NextGraph n'a pas :
« je nomme mon identité ». Le premier consommateur en avait ~300 lignes — un
gate, un écran, un module wallet, un contexte d'identité, trois features. C'est
le travail de la bibliothèque, pas le sien.
`ensureIdentity()` : un appel, avant que l'app s'affiche. Il ne prend PAS
d'identifiant — nommer une identité est l'étape qui disparaîtra, donc elle ne
doit pas figurer dans la signature. Le jour où le wallet fournit l'identité,
l'appel se résout sans rien afficher et le code de l'appelant ne bouge pas.
L'écran est en DOM natif, sous shadow root : c'est une barrière technique
montrée avant qu'une application s'affiche, comme une demande de mot de passe
sur une bêta fermée. La lier à un framework obligerait chaque consommateur à
adopter ce framework pour un écran voué à disparaître.
L'ordre de résolution de l'identité est pinné par des tests, parce que s'y
tromper échoue en SILENCE : le parcours traverse deux partitions localStorage
distinctes — la page et l'iframe du broker — et seul l'URL franchit la
frontière. Si le stockage l'emportait, l'iframe lirait une identité vide,
provisionnerait un second utilisateur virtuel, et l'utilisateur reviendrait dans
un espace vide sans la moindre erreur.
Les identifiants du wallet partagé (fichier, mot de passe) passent par
`configure()` : ce sont des données de déploiement, et cet appel est déjà celui
qui devient inerte à la migration. Au passage, l'ancien champ `sharedWallet:
{ name, secret }` — inutilisé nulle part — est remplacé.
168 tests unitaires, typecheck vert.