Ng eventually #1
@@ -1,12 +1,12 @@
|
||||
---
|
||||
type: brief
|
||||
summary: Stopgap staging multi-user — deux visions cadrées. Lointaine (cible) — multi-wallet, 3 stores natifs par utilisateur + Dialog, 1 document par entité (événement/PdR), partage par capabilities, inbox native du PdR. Adaptée (stopgap) — UN wallet partagé, 1 document par entité dans son private_store, périmètre = métadonnée logique + index, filtre d'isolation applicatif, login simulé. Obstacles NextGraph — pas de lecture cross-wallet (OpenRepo TODO, ReadCap ignoré), capabilities/inbox non exposées au SDK, login non programmable. Shim livré in-app (storeRegistry/comptes/isolation) ; le filtre de lecture est désormais dans la lib ng-eventually (cf. decision_2026-06-17). sharedWalletShim + filtre = jetables à la migration.
|
||||
last_updated: 2026-06-16
|
||||
summary: Stopgap staging multi-user — deux visions cadrées. Lointaine (cible) — multi-wallet, 3 stores natifs par utilisateur + Dialog, 1 document par entité (événement/PdR), partage par capabilities, inbox native du PdR. Adaptée (stopgap) — UN wallet partagé, 1 document par entité dans son private_store, périmètre = métadonnée logique + index, filtre d'isolation applicatif, login simulé. Obstacles NextGraph — pas de lecture cross-wallet (OpenRepo TODO, ReadCap ignoré), capabilities/inbox non exposées au SDK, login non programmable. Shim désormais ENTIÈREMENT dans la lib ng-eventually (2026-07-02) : namespaces docs/storeRegistry/isolation/accounts ; l'app ne touche @ng-org au runtime que via ngSession (cf. decision_2026-06-17). sharedWalletShim + filtre = jetables à la migration.
|
||||
last_updated: 2026-07-02
|
||||
---
|
||||
|
||||
# Stopgap multi-user : wallet partagé unique (`sharedWalletShim`)
|
||||
|
||||
**Status:** En cours — compte/login + isolation livrés et vérifiés ; **granularité 1 document par entité implémentée** ; primitives + **fan-out multi-documents validés sur broker** (`@data`, 3 scénarios). Reste : reactivity in-app de la création (best-effort) + seeding multi-doc. **Le filtre de lecture a migré dans la lib `ng-eventually` (ReadCap par document, cf. [[decision_2026-06-17_eventually-library]])** ; le reste du shim (storeRegistry/comptes/isolation) est encore in-app, destiné à rejoindre la lib.
|
||||
**Status:** **Shim entièrement migré dans la lib `ng-eventually` (2026-07-02)** — `storeRegistry`, couche comptes, filtre d'isolation **et** primitive `doc_create`/SPARQL vivent maintenant dans `@ng-eventually/client` (namespaces `docs`/`storeRegistry`/`isolation`/`accounts`), en plus du filtre de lecture ReadCap déjà porté. L'app ne consomme plus que la lib ; le domaine Festipod (mapping entité→scope, connexions, wrapper React des comptes) reste **injecté** côté app. Seul `ngSession.configure` touche encore `@ng-org` au runtime (+ 2 exceptions test-harness). Validé : lib 36/36 + `tsc` rc=0 ; suite BDD **78 passed / 0 failed / 71 skipped**. Détails dans [[decision_2026-06-17_eventually-library]] (§ « Shim migré dans la lib — 2026-07-02 »). Reste fonctionnel (indépendant de la migration) : reactivity in-app de la création (best-effort) + seeding multi-doc.
|
||||
|
||||
## Objectif & posture
|
||||
|
||||
@@ -22,7 +22,7 @@ Trois choses doivent rester nettes pour ne pas dériver, et structurent ce brief
|
||||
|
||||
---
|
||||
|
||||
> **Direction (2026-06-17 → en cours)** : ce polyfill a vocation à être **encapsulé dans une librairie générique externe** (`ng-eventually-js`, hors repo) plutôt que dispersé dans l'app — voir [[decision_2026-06-17_eventually-library]]. **Déjà fait** : le routage du SDK (`useShape`/`init`/`ng`) et le **filtre de lecture ReadCap** (par document) vivent dans `@ng-eventually/client`. **Encore in-app** (livré par le stopgap décrit ci-dessous) : `storeRegistry`, couche comptes, filtre d'isolation — à migrer dans la lib ensuite. L'app ne dépend déjà plus directement du SDK que par un point d'injection unique (`ngSession.configure`).
|
||||
> **Direction (2026-06-17 → ATTEINTE 2026-07-02)** : ce polyfill devait être **encapsulé dans une librairie générique externe** (`ng-eventually-js`, hors repo) plutôt que dispersé dans l'app — voir [[decision_2026-06-17_eventually-library]]. **C'est fait, en totalité** : le routage du SDK (`useShape`/`init`/`ng`), le filtre de lecture ReadCap, **et** désormais `storeRegistry`, la couche comptes, le filtre d'isolation et la primitive `doc_create`/SPARQL vivent tous dans `@ng-eventually/client` (namespaces `docs`/`storeRegistry`/`isolation`/`accounts`, zéro Festipod — le domaine est injecté). L'app ne touche `@ng-org` au runtime que par le point d'injection unique `ngSession.configure` (+ 2 exceptions test-harness documentées). La description « encore in-app » du stopgap ci-dessous est donc **historique** : lire les fichiers cités comme des wrappers minces au-dessus de la lib.
|
||||
|
||||
## 1. Vision lointaine (cible finale)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: decision
|
||||
summary: Tout le polyfill multi-user (wallet partagé, caps émulées, inbox émulée) est encapsulé dans une LIBRAIRIE GÉNÉRIQUE externe « ng-eventually-js » (repo hors Festipod, à côté de nextgraph-rs/orm-tests), zéro Festipod dedans. UN package pour l'instant : @ng-eventually/client (entrée principale SDK-IDENTIQUE ; bootstrap polyfill isolé sous /polyfill ; l'app n'en dépend que de lui). Le curateur d'index global (ex-@ng-eventually/service) est RETIRÉ/différé : son modèle « backend à données globales » est incorrect — NextGraph est mono-utilisateur sans données globales (cf. knowledge_apps-and-services) ; un index global passerait par une app singleton (incertain, différé, à creuser). Migration = alias de build retiré + le client redevient le vrai SDK. Festipod ne dépend que de @ng-eventually/client.
|
||||
last_updated: 2026-06-17
|
||||
last_updated: 2026-07-02
|
||||
---
|
||||
|
||||
# Décision 2026-06-17 — Librairie « ng-eventually-js » (polyfill encapsulé)
|
||||
@@ -70,6 +70,20 @@ Imports `@ng-org` runtime de l'app après merge : point d'injection (`ngSession`
|
||||
|
||||
**Encore in-app** (à migrer dans la lib ensuite) : `storeRegistry`, `AccountContext`, filtre d'**isolation** (`isolation.ts`) — distinct du filtre **ReadCap** de la lib ([[brief_2026-06-15_shared-wallet-shim]]). **TODO lib** : exposer une primitive `doc_create`/SPARQL côté lib qui utilise le `ng` injecté (évite le double-proxy) pour que l'app n'ait plus jamais besoin du `ng` direct.
|
||||
|
||||
### Shim migré dans la lib — TERMINÉ & validé (2026-07-02)
|
||||
|
||||
Le TODO ci-dessus est **fait** : **tout le shim est désormais DANS la lib**. La frontière d'intégration a bougé de « `doc_create` reste sur le vrai `ng` / shim encore in-app » à **« tout est dans la lib ; l'app ne touche `@ng-org` au runtime que via `ngSession` »**.
|
||||
|
||||
- **Primitive `doc_create`/SPARQL — FAITE.** Namespace **`docs`** de la lib : `docCreate(sessionId, crdt, cls, dest, store?)`, `sparqlUpdate(sessionId, query, anchor?)`, `sparqlQuery(sessionId, query, base?, anchor?)`. En interne appelle le **`ng` RÉEL injecté** (`getConfig().ng`), **JAMAIS** le proxy public `makeNg` → pas de double-proxy, pas de `DataCloneError`. C'est la résolution de la limite du 2026-06-30.
|
||||
- **Nouvelles surfaces lib** (exposées en **namespaces** dans `src/index.ts`, calquées sur `docs`/`inbox`) :
|
||||
- **`storeRegistry`** — mécanique générique (résolveur `(account, scope)→NURI`, `createEntityDoc`/`listEntityDocs` + index par périmètre, `sharedWalletShim` ancré dans le `private_store`, cache, `ensureAccount`/`allAccounts`). **Zéro Festipod** : le mapping entité→scope (`EntityKind`/`entityScope`) reste **injecté par l'app** via `configureStoreRegistry({ getSession, normalizeUser })`.
|
||||
- **`isolation`** — `applyIsolation` **pur** (matrice public=tous / protected=owner+connexions / private=owner) ; accessors (`ownerOf`/`scopeOf`) **et** le graphe de connexions **injectés par le consommateur** — la lib n'invente pas les connexions.
|
||||
- **`accounts`** — `AccountStore` (faux login localStorage, storage **injecté**) + `normalizeUsername`. Le wrapper **React** (`Context`/`Provider`) **n'est PAS porté** : il reste dans l'app (couche mince), la lib n'impose pas React.
|
||||
- **Décision isolation↔ReadCap = COEXISTENT** (ne pas fusionner) : axes distincts — **ReadCap** = capacité **par-document** broker-native ; **isolation** = visibilité **sociale par-item** (owner + scope + graphe de connexions). Le `protected` dérivé des connexions n'a pas d'équivalent dans le modèle doc-cap.
|
||||
- **App recâblée** : `storeRegistry.ts` = `EntityKind`/`entityScope` + `configureStoreRegistry` + ré-export de la lib ; `AccountContext` = wrapper mince (clé historique `festipod.account.username` épinglée → zéro changement de comportement) ; `isolation.ts` = wrapper Festipod sur la lib ; `harness-ng.tsx` `createSmokeDoc` = `docs.docCreate`.
|
||||
- **Invariant atteint** : `grep -rn "from '@ng-org" src/ | grep -v "import type"` ne liste plus que **`ngSession`** (injection `configure`) + les 2 exceptions test-harness documentées (`auth-setup.tsx`, `harness.tsx`/`deepSignal`). Plus aucun `doc_create` via le proxy public.
|
||||
- **Validation** : lib **36/36 `bun test` + `tsc --noEmit` rc=0** ; app `bun run build` + bundle `harness-ng` OK ; **suite BDD complète 78 passed / 0 failed / 71 skipped** (baseline 2026-06-30 respectée, dont les 3 `@data` multistore, `@humain`, ReadCap `@data`).
|
||||
|
||||
## Open Questions
|
||||
|
||||
- **Curateur d'index / index global** : package `@ng-eventually/service` **retiré pour l'instant** (2026-06-21) — modèle « backend » incorrect ([[knowledge_apps-and-services]]). À **réintroduire** (et nommer : curateur/admin) quand le **mécanisme cible d'index global** sera tranché (app singleton ? voie plus simple ?) — incertain, **à creuser plus tard**.
|
||||
|
||||
Reference in New Issue
Block a user