fix(@data): round-trip the seed/read path against the real broker

Multiple compounding defects kept the connected @data read at 0 entities:
- writeEntity/updateEntityField and registration helpers wrote into an explicit
  GRAPH <plainNuri> named graph, invisible to the anchored default-graph read
  (read-model.readDoc) after the read switched to per-doc anchored. Drop the
  wrapper so writes land in the repo's default graph (matches the read).
- Seed entities are now owned by the CURRENT account, so protected seed docs
  (user profiles) pass the per-document ReadCap gate and round-trip.
- Suppress the double seed (explicit loadTestData + 3s dev auto-seed) and add a
  re-list signal so freshly-seeded protected docs enter the read set.
- @data step awaits the seed result and waits for events AND users > 0.

Documents the anchored-default-graph write pitfall in rule_document-per-entity.

Validated: connexion-nextgraph.feature @data = 4 scenarios / 13 steps green.
NB: the shared test wallet's private store bloats across runs and makes anchored
queries hang (>15s); a fresh .playwright-profile restores ~1.5s — durable wallet
hygiene is a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Duchesne
2026-07-06 12:46:39 +02:00
parent 02cda056b8
commit 0911b1f9de
8 changed files with 163 additions and 84 deletions
-9
View File
@@ -1,9 +0,0 @@
# 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/data/readEntities.ts @2026-07-05 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
- TOUCHED src/shared/context/FestipodDataContext.tsx @2026-07-05 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
- TOUCHED src/shared/utils/ngBootstrap.ts @2026-07-06 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
@@ -73,7 +73,19 @@ synchrone (boucle de seed, première création). Contre le vrai broker, un `add`
lève « Set is readonly because scope is empty » (les tests unitaires fake-ng ne l'attrapent pas).
Donc : **écriture = SPARQL direct dans le doc de l'entité** (immédiat, par-document) ;
**lecture = union + re-query** (ci-dessus). Idem pour la **mutation d'un champ** existant (p. ex. `participantCount`) : muter une valeur
**lecture = union + re-query** (ci-dessus).
**Piège de graphe (INSERT/DELETE sans wrapper `GRAPH`).** L'écriture doit viser le **graphe par
défaut** du document — on passe le NURI du document comme **ancre** de `docs.sparqlUpdate` et on
écrit le corps SPARQL **sans** clause `GRAPH <…>` explicite. La lecture union interroge elle aussi
le graphe par défaut ancré (`readEntities`/`readUnion`) ; un corps enveloppé dans un
`GRAPH <nuriDuDoc>` explicite écrit dans un graphe **nommé distinct** que cette lecture ne voit
pas → l'entité ne fait jamais l'aller-retour (elle « disparaît » silencieusement). Vaut pour
`writeEntity`, `updateEntityField` et les écritures de `registration.ts`. (Le *pourquoi* côté SDK
— comment l'ancre restreint la requête au graphe du repo — appartient au SDK `@ng-eventually/client`,
pas ici.)
Idem pour la **mutation d'un champ** existant (p. ex. `participantCount`) : muter une valeur
en mémoire ne tient pas — la re-query union relit la valeur **persistée** depuis le broker
(retour à l'ancienne valeur) → persister via SPARQL (`updateEntityField` : DELETE puis
INSERT du triplet) pour que le changement tienne et que la relecture concorde. Chaque champ est écrit avec le **bon terme RDF** selon la shape SHEX (xsd:integer /