From d69fd7a5f9e8fd4bc214b715e2c7a817ce5644c1 Mon Sep 17 00:00:00 2001 From: Sylvain Duchesne Date: Tue, 30 Jun 2026 13:39:53 +0200 Subject: [PATCH] Revert doc_create to real ng: lib proxy breaks iframe marshaling (validated) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full-suite validation of the merge surfaced 4 failures, all multistore: routing doc_create through the lib's `ng` proxy (685f6d3) breaks @ng-org/web's iframe postMessage marshaling — DataCloneError "function could not be cloned" (a JS Proxy over the iframe-RPC proxy = double proxy). Fix: storeRegistry.ts and harness-ng.tsx (createSmokeDoc) call doc_create / SPARQL on the real @ng-org/web `ng` directly again. useShape / init / login / ReadCap still route through the lib. After the fix the 3 multistore scenarios pass; full suite = 77 passed, 0 merge regressions. Integration boundary documented in decision_2026-06-17: the in-app shim's low-level NextGraph calls stay on the real SDK until storeRegistry moves INTO the lib (where it would use the injected real ng, no double proxy). Lib TODO: expose a doc_create/SPARQL primitive that uses the injected ng. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../decision_2026-06-17_eventually-library.md | 12 +++++++++++- src/shared/test-harness/harness-ng.tsx | 7 +++++-- src/shared/utils/storeRegistry.ts | 8 +++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.project/concepts/nextgraph-platform/decision_2026-06-17_eventually-library.md b/.project/concepts/nextgraph-platform/decision_2026-06-17_eventually-library.md index 043942d..8d81217 100644 --- a/.project/concepts/nextgraph-platform/decision_2026-06-17_eventually-library.md +++ b/.project/concepts/nextgraph-platform/decision_2026-06-17_eventually-library.md @@ -58,7 +58,17 @@ Reste à implémenter dans la lib (stubs `TODO`, nécessitent la couche comptes/ ### Intégration du shim mono-wallet (merge 2026-06-30) -Le merge de `main` (shim staging wallet partagé : `storeRegistry`, comptes, isolation, e2e multi-navigateur) a ramené du code écrit contre le SDK brut. **Audit post-merge** : le seul écart à l'invariant « tout passe par `@ng-eventually/client` » était `storeRegistry.ts` qui importait `ng` de `@ng-org/web` ; **corrigé** → il importe `ng` de la lib (le proxy forwarde `doc_create`/`sparql_update`/`sparql_query`). Désormais, les **seuls** imports `@ng-org` runtime de l'app sont le **point d'injection** (`ngSession`) + les exceptions documentées (`auth-setup`, `harness` mock) + les bindings ORM générés (`import type`). L'invariant tient. **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]]). +Le merge de `main` (shim staging wallet partagé : `storeRegistry`, comptes, isolation, e2e multi-navigateur) a ramené du code écrit contre le SDK brut. + +**Limite découverte (validée en suite complète, 2026-06-30)** : `doc_create` (et les appels SPARQL du shim) **ne peuvent PAS passer par le proxy `ng` de la lib**. Le `ng` de `@ng-org/web` est déjà un **proxy iframe (RPC postMessage)** ; l'envelopper dans le `Proxy` JS de `makeNg` (double proxy) casse le marshaling de `doc_create` → `DataCloneError: function ... could not be cloned`. Tenté (`storeRegistry`+`harness` routés via la lib) → **4 scénarios multistore rouges** ; **annulé**. + +**Frontière d'intégration retenue** : +- **Passent par la lib** (validés) : `useShape` (ORM + filtre ReadCap), `init`/`initNg`, `login`. +- **Restent sur le vrai `ng`** (`@ng-org/web`) : `doc_create` + SPARQL du shim — dans `storeRegistry.ts` (app) et `harness-ng.tsx` (`createSmokeDoc`). C'est cohérent avec « shim **encore in-app** » : quand `storeRegistry` **migrera dans la lib**, il utilisera le `ng` **réel injecté** (`getConfig().ng`) en interne — **pas** le proxy public → plus de double-proxy. + +Imports `@ng-org` runtime de l'app après merge : point d'injection (`ngSession`) + `storeRegistry`/`harness-ng` (doc_create, le temps que le shim rejoigne la lib) + exceptions documentées (`auth-setup`, `harness` mock) + bindings ORM `import type`. + +**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. ## Open Questions diff --git a/src/shared/test-harness/harness-ng.tsx b/src/shared/test-harness/harness-ng.tsx index 821d115..88b68cf 100644 --- a/src/shared/test-harness/harness-ng.tsx +++ b/src/shared/test-harness/harness-ng.tsx @@ -11,10 +11,13 @@ import React, { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NextGraphProvider, useNextGraph } from '../context/NextGraphContext'; import { FestipodDataProvider, useFestipodData } from '../context/FestipodDataContext'; -// useShape + ng routed through the lib (SDK-identical surface); caps from /polyfill. -import { useShape, ng } from '@ng-eventually/client'; +// useShape routed through the lib (SDK-identical surface); caps from /polyfill. +import { useShape } from '@ng-eventually/client'; import { getCaps, setCurrentUser, resetCaps } from '@ng-eventually/client/polyfill'; import type { DeepSignalSet } from '@ng-eventually/client'; +// doc_create goes straight to the real SDK: the lib's `ng` proxy over @ng-org's +// iframe-RPC proxy breaks doc_create's postMessage marshaling (see storeRegistry). +import { ng } from '@ng-org/web'; import { FpEventShapeType, FpUserProfileShapeType, diff --git a/src/shared/utils/storeRegistry.ts b/src/shared/utils/storeRegistry.ts index 46539c4..a17862e 100644 --- a/src/shared/utils/storeRegistry.ts +++ b/src/shared/utils/storeRegistry.ts @@ -25,7 +25,13 @@ * against the verified SDK surface but must be validated against a live broker. */ -import { ng } from '@ng-eventually/client'; +// doc_create / SPARQL go straight to the real SDK: the lib's `ng` proxy (a JS +// Proxy over @ng-org's iframe-RPC proxy) breaks doc_create's postMessage +// marshaling (DataCloneError). useShape/login/ReadCap DO route through the lib; +// this low-level path stays direct until storeRegistry moves INTO the lib (where +// it would use the injected real ng, no double-proxy). See +// decision_2026-06-17_eventually-library. +import { ng } from '@ng-org/web'; import { sessionPromise } from './ngSession'; import { normalizeUsername } from '../context/AccountContext';