refactor(app): l'app lit via watchShape (useShapeQuery), plus de machinerie bespoke

Phase B — FestipodDataContext lit désormais via la surface SDK `watchShape`
(binding `useSyncExternalStore` dans `useShapeQuery`) + adaptateurs Fp
(`shapeAdapters.ts`), au lieu de sa machinerie maison. Applique
rule_app-uses-sdk-surface-only : l'app ne consomme que la surface SDK.

Supprimé : `readEntities.ts`, `subscribeDocs`+`bumpRead`+`readTick`+`readDocKey`,
le listing manuel (`publicDocs`/`protectedDocs`/`registerDoc` pour la lecture,
`readDiscoveredEvents`), et les commentaires raisonnant sur le hang ORM. Gardé
découplé : `listMyEntityDocs(owner,'public')` → `ownedEventIds` pour le seul
matérialiseur propriétaire.

Auto-seed : chronomètre 3 s → gate `isSuccess` (seed uniquement si synchronisé ET
vide) — fix du re-seed « First time… » au 3ᵉ connect. Mode démo inchangé.

Non-régression VÉRIFIÉE (broker réel, wallet frais) : inscription (1 passed),
isolation « identité fraîche ne voit pas » (re-run local, 5 steps passed), compteur
dérivé/Q4 (1 passed). tsc propre, build OK.

Résiduel PRÉ-EXISTANT (pas causé par ce refactor, vérifié par stash sur baseline) :
- reconnexion « relit ses propres données » → RE-@wip : défaut cold-read de l'index
  de scope PUBLIC côté lib (une page fraîche relit vide) — prochaine cible.
- un @AUTH « données pas rechargées » (timing loadFire-and-forget vs step 30 s).

Doctrine : rule_app-uses-sdk-surface-only « déviation résolue ».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Duchesne
2026-07-09 23:46:31 +02:00
parent 2295af610a
commit 38266d96f8
7 changed files with 288 additions and 409 deletions
@@ -28,14 +28,17 @@ contournements (read-model union à la place du fan-out ORM, `open-repo`, readin
miroir de `readyPromise`, émulation de caps…) sont **internes au polyfill** et
n'apparaissent jamais dans l'app.
## Déviation actuelle (dette à corriger)
## État (déviation résolue)
`src/shared/data/readEntities.ts` + `FestipodDataContext` lisent via
`readModel.readUnion` + `subscribeDocs` + `bumpRead`, avec un commentaire qui explique
que ça « remplace le fan-out `useShape` qui hang ». C'est la fuite exacte que cette
règle interdit.
**Résolu** : `FestipodDataContext` lit désormais via `useShapeQuery` (binding
`useSyncExternalStore` sur `watchShape` du polyfill) + adaptateurs Fp
(`src/shared/data/shapeAdapters.ts`). Sont **supprimés** : `readEntities.ts`, la
réactivité bespoke (`subscribeDocs`+`bumpRead`+`readTick`), le listing manuel
(`publicDocs`/`protectedDocs`/`registerDoc` pour la lecture), et les commentaires
raisonnant sur le hang ORM. L'auto-seed est gardé sur `isSuccess` (plus de
chronomètre 3 s). L'app ne consomme plus que la surface SDK.
**Cible** : le polyfill expose un `useShape` **réactif, scopé au wallet virtuel**, dont
**Cible (rappel du design)** : le polyfill expose un `useShape` **réactif, scopé au wallet virtuel**, dont
la **forme suit TanStack `useQuery`**`{ data, isPending/isLoading, isSuccess, isError,
… }`**en anticipation de la mise à jour PRÉVUE de `useShape` par NextGraph** (qui va
adopter ce fonctionnement). Ce n'est donc pas une invention : c'est une API future de