docs(concept): durabilité écriture↔déconnexion, décision wallet-partagé-unique, rule_bun-first (install pnpm)
caveat_write-durability-across-disconnect + decision_2026-07-20 (wallet partagé = seul mode ; identifiant ≠ username profil) + amendement bun-first. Marqueurs _debt.md inclus (voyagent avec la branche, à réconcilier avant push). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014GbGgNEHRejVKoREvFuDFg
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# Doc-debt — data-layer
|
||||
|
||||
> 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 src/shared/context/FestipodDataContext.tsx @2026-07-14 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
- TOUCHED src/shared/utils/ngSession.ts @2026-07-20 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
@@ -2,7 +2,7 @@
|
||||
type: _overview
|
||||
summary: Comment Festipod persiste ses données via le SDK @ng-eventually/client — entités stockées comme documents par scope, écriture SPARQL directe + lecture par modèle union, stack SHEX, modes connected/demo, seed
|
||||
triggers:
|
||||
keywords: [nextgraph, "@ng-eventually", union, readUnion, readEntities, SHEX, shape, scope, "@graph", NURI, sparql, seed, wallet, FestipodData, ngSession, ngGraph, bootstrap, document, entité]
|
||||
keywords: [nextgraph, "@ng-eventually", union, readUnion, readEntities, SHEX, shape, scope, "@graph", NURI, sparql, seed, wallet, FestipodData, ngSession, ngGraph, bootstrap, document, entité, déconnexion, reconnexion, durabilité, outbox, SerializationError]
|
||||
paths: ["src/shared/shapes/**", "src/shared/data/readEntities.ts", "src/shared/data/entityWrites.ts", "src/shared/context/NextGraphContext.tsx", "src/shared/context/FestipodDataContext.tsx", "src/shared/utils/ng*", "src/shared/data/seedData.ts"]
|
||||
---
|
||||
|
||||
@@ -28,5 +28,6 @@ Comment Festipod **persiste ses données** via NextGraph (P2P, local-first, chif
|
||||
|
||||
- [[caveat_participation-deletion]] — la désinscription doit être **autoritative** et ne pas réapparaître
|
||||
- [[caveat_event-fields-not-persisted]] — `startTime`/`themes`… non couverts par la shape Event → perdus en connecté
|
||||
- [[caveat_write-durability-across-disconnect]] — une écriture juste avant une inactivité/chute de socket peut être **perdue** (non durable broker) ; compte survit. Incident ouvert → post-mortem dans le polyfill
|
||||
|
||||
> Confidentialité (isolation par scope, confiance dans le SDK) : concept `app-security`. Périmètres produit par entité + découverte : concept `functional-domain`.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
type: caveat
|
||||
summary: Une entité écrite juste avant une inactivité/chute de socket peut être perdue silencieusement (jamais durable côté broker) ; le compte survit (pas de fork). Observé Firefox. Le SDK ne confirme pas la durabilité et ne se reconnecte pas seul.
|
||||
last_checked: 2026-07-14
|
||||
---
|
||||
|
||||
# Piège : une écriture juste avant une déconnexion n'est pas garantie durable
|
||||
|
||||
**Symptôme produit.** L'utilisateur crée une entité (un événement), ça semble réussir, puis une **période d'inactivité** survient ; au rechargement / à la reconnexion, l'entité a **disparu**. Le scope se relit **vide**. L'**identité/compte survit** — ce n'est PAS un fork, c'est une écriture non durable.
|
||||
|
||||
**Mécanisme (résumé, non tranché).** Le socket broker peut mourir spontanément pendant l'idle (`SOCKET IS CLOSED … SerializationError`). L'écriture était dans l'outbox local ; au retour, le replay échoue (`Err(TopicNotFound)`) et l'entité est abandonnée. **Observé Firefox uniquement** à ce jour. Un test @data à froid (2026-07-14) a par ailleurs montré qu'une session **fraîche** (aucun état local, même compte A) ne récupère **pas** le scope propre de A depuis le broker : le test de reconnexion @data qui « passait » relisait en fait l'IndexedDB **locale**. Reste à trancher : **perte à l'écriture** vs **échec de réhydratation à froid** (mécanismes distincts) — voir le post-mortem dans le polyfill.
|
||||
|
||||
**Pourquoi l'app ne le voit pas.** `NgStatus` est dérivé **une seule fois** de la session initiale → aveugle aux chutes en cours de session. Le canal `disconnections_subscribe` du SDK se déclenche sur la panne mais **n'est pas consommé** (ni polyfill ni app). Aucune API ne confirme qu'une écriture a atteint le broker.
|
||||
|
||||
**Ne pas documenter ici les internes NextGraph.** Frontière SDK (voir [[knowledge_nextgraph-stack]]) : cause racine, chaîne causale (socket, reconnexion en TODO) et pistes de correction vivent dans le repo `@ng-eventually/client` → `docs/incidents/2026-07-14-write-loss-on-disconnect.md`. Cette fiche ne garde que l'**impact consommateur** + le pointeur.
|
||||
|
||||
**Statut : ouvert, non traité (2026-07-14).** À revisiter quand le core/SDK adresse la reconnexion ou expose une confirmation de durabilité — ce caveat tombera alors. Voir aussi le débat lecture-à-froid vs perte réelle dans [[brief_2026-07-06_reactive-reads-and-attendance]] (le `BARRIER timed-out` de @data est une signature distincte, non confirmée comme ce bug).
|
||||
Reference in New Issue
Block a user