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.
3.1 KiB
ADR — Use a store NURI as the useShape scope AND @graph
Date: 2026-03-17 · Status: Accepted (partially superseded — see below). Historical decision, ported into this lib because the insight still governs how the shim opens repos. Original context: the consuming app.
Partially superseded (2026-07-03). The private-store-only scope was replaced for shareable domain entities: they are now scoped AND written to the protected store (
did:ng:${protected_store_id}), verified to open withoutRepoNotFound. The central insight of this ADR still holds and now applies to both stores: you must open the repo via the store's NURI or you getRepoNotFound. (How it is opened has since changed — see the note under Decision.)
Context
Loading test data updated the in-memory ORM signals (immediate UI) but produced
RepoNotFound on doc_create and orm_frontend_update. Data vanished on reload
because the SPARQL writes never reached the broker: the verifier's self.repos
HashMap did not contain the store's repo → resolve_target() failed.
Options considered
A — did:ng:i scope + doc_create for @graph
did:ng:i is documented as a subscription scope; doc_create returns a real
NURI. Against: did:ng:i goes through NuriTargetV0::UserSite, which does
NOT open individual repos; doc_create calls resolve_target(PrivateStore),
which requires the repo already in self.repos → fails; needs complex retry/timing.
B — the store NURI as scope AND @graph (chosen)
Exact copy of the working expense-tracker-rdf example: orm_start_graph with
the store's NURI opens the repo in self.repos; subsequent orm_frontend_update
finds it. Simple, no retry. Against: slightly less flexible than did:ng:i
(scoped to one store); requires passing the session down to the ORM hook.
C — did:ng:i scope + reuse an existing entity's @graph
Works for users who already have data. Against: fails for empty wallets (no
entity to reuse) → falls back to doc_create and the same RepoNotFound.
Decision
Option B: use the store NURI as both the useShape scope AND the write
@graph, exactly like expense-tracker-rdf. This is why this lib's shim opens the
store repo before writing, and why did:ng:i must never be used as a scope (it
breaks writes with RepoNotFound). See the scope rule in
../simulation.md.
The decision stands; the mechanism named in it has been replaced. Opening was
orm_start_graph when this was written. It is now ensureRepoOpen — doc_subscribe
plus a wait for the first State (packages/sdk/src/emulated-verifier/open-repo.ts:167) — after
orm_start_graph was found to hang on a fan-out (subscribe.ts:28,181). What must be
read here is the invariant "open the repo, by its store NURI, before writing", not the
call that used to implement it.
Consequences
- Positive: immediate writes after connect (no retry); persistence across reload; aligned with the official examples.
- Risk: if NextGraph changes the store's open behaviour, this breaks.