Commit Graph

3 Commits

Author SHA1 Message Date
Sylvain Duchesne aa6bbc436e test(e2e): les parcours applicatifs passent par l'app d'exemple
Une seconde suite e2e, `packages/sdk/e2e/notebook.ts` (`test:e2e:app`), qui pilote
`examples/notebook` par le DOM — une page de navigateur par identité — contre le même
broker réel.

**Pourquoi une seconde suite plutôt qu'un ajout dans la première.** `run.ts` parle à un
sac de méthodes sur `window.__sdk` : cela prouve que les fonctions TOURNENT, jamais
qu'une application peut s'écrire avec. L'écart a déjà coûté un défaut livré — l'inbox
d'un document était verte ici et inutilisable en pratique, parce que le harnais pouvait
faire traverser une adresse d'une identité à l'autre par une variable, canal qu'aucune
application n'a. Ici, rien ne traverse que ce qui traverse dans la vie : la RÉFÉRENCE
d'une note, recopiée d'un écran, et un identifiant tapé dans un champ.

Quatre parcours, qui se lisent comme des parcours :

- Bob lit la note publique d'Alice depuis sa seule référence — la propriété pour
  laquelle l'émulation du store public existe, vérifiée bout en bout et sans qu'aucune
  clé ne circule ;
- la note protégée d'Alice reste fermée jusqu'à ce qu'elle la partage — même geste côté
  Bob, issue opposée, décidée par où la note se trouve ;
- Bob laisse un message sur la note d'Alice, et seule Alice le lit — il TROUVE l'adresse
  depuis la note, personne ne la lui donne ;
- la liste de chacun ne contient que ses notes.

**Deux étapes quittent `run.ts`** (`documentInboxDeposit`, `capsShareCap`), avec un
commentaire disant où elles sont parties : ce sont des parcours, et ils valent plus joués
sur deux écrans que sur deux appels d'une même page. Ce qui reste là-bas est ce qu'une
application ne fait pas : primitives, caractérisation, régressions de démarrage à froid.

**Trois défauts trouvés en écrivant la suite**, tous côté application et invisibles pour
le harnais : `connectedUser()` devait être attendu à la connexion (sinon une note qu'on
vient de vous partager se lit comme illisible — ce qui ressemble à un problème de droits
alors que c'est un problème de moment) ; une réponse périmée restait affichée à côté
d'une question fraîche ; et changer de portée ne rafraîchissait pas la liste. L'app
affiche désormais la référence de chaque note — ce qu'aucun écran ne montre, aucun
utilisateur ne peut le faire circuler.

Corrigé au passage : le `.gitignore` pointait encore `packages/client/`, si bien que le
commit de renommage a embarqué le profil Playwright de la suite e2e (226 fichiers). Les
chemins sont réalignés et le commit précédent a été amendé — rien n'était poussé.

179 tests unitaires, e2e 40/40 (3,2 min) et applicatif 10/10 (0,7 min).
2026-08-07 11:20:58 +02:00
Sylvain Duchesne 0eb25286c8 refactor: renommer client → sdk, et fusionner les deux portes en une
Deux mouvements de surface, aucun changement de comportement.

**`packages/client` → `packages/sdk`, `@ng-eventually/client` → `@ng-eventually/sdk`.**
« client » ne disait rien : ce paquet EST le SDK que l'application appelle, et c'est
tout ce qu'elle appelle. L'ancien nom reste comme mot-clé de recherche dans
`docs/source-layout-by-fate.md` et le tableau des paquets du README.

**Une seule entrée.** L'entrée `./polyfill` disparaît ; ses symboles applicatifs —
`configure`, `configureStoreRegistry`, `setCurrentUser`, `connectedUser` et leurs types
— vivent dans un bloc `POLYFILL-ERA` de `src/index.ts`.

Ce que la seconde porte portait mérite d'être nommé avant d'être retiré : *ce qu'on
importe de ce chemin est exactement ce qu'on supprimera à la migration*. Une seule
porte perd ce signal — rien à la ligne d'import ne distingue `configure`, qui part, de
`docs`, que le vrai SDK remplace sur place. Trois choses le portent désormais : le bloc
lui-même, l'inventaire d'exports de `docs/api-contract.md` (épinglé par
`test/vocabulary.test.ts`, donc il ne peut pas rancir en silence), et le contrôle de
vocabulaire sur les noms publiés.

**Six symboles quittent la surface au passage**, et la fusion est ce qui a rendu le
choix visible plutôt qu'hérité :

- `getConfig` / `getStoreRegistryDeps` — câblage interne, atteint par
  `shared-wallet/bootstrap` ;
- `resetConfig` / `resetStoreRegistry` / `resetCaps` — remises à zéro de test, atteintes
  par leur chemin interne, ce qui est leur raison d'être ;
- le `share` direct — `inbox.share` a toujours été la même fonction, et la publier deux
  fois brouillait la frontière qu'elle servait à marquer.

Corrections d'affirmations fausses trouvées en chemin : le contrat annonçait `isNuri` /
`hasReadCap` sur la porte SDK alors qu'ils ne sont plus exportés depuis le passage au
permissif en entrée (`NuriLike` validé à la porte) ; le README du paquet documentait
`capFor`, `shareCap`, `getCaps` et `publishRepoLink`, dont aucun n'existe ; et le README
de l'app d'exemple affirmait que la suite e2e la pilote, ce qui reste à faire.

179 tests unitaires, typecheck bibliothèque / exemple / harnais, e2e 42/42 contre le
broker en ligne — mesuré une fois après le renommage, une fois après la fusion.
2026-08-07 11:16:57 +02:00
Sylvain Duchesne d35e735c8b feat(example): une app d'exemple, écrite comme un consommateur
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.
2026-08-05 18:25:47 +02:00