doctrine+dev: règle « app = surface SDK seule » + access-log par défaut

- rule_app-uses-sdk-surface-only : l'app se comporte comme si NextGraph était fini
  et sans défaut ; elle lit via `useShape` (scopé wallet virtuel, fourni par le
  polyfill), jamais via des internes (readModel/subscribeDoc) ni en raisonnant sur
  un problème NextGraph. Raison d'être du polyfill = le WALLET VIRTUEL (pas le hang
  ORM, qui n'est qu'un détail interne). Cible : `useShape` polyfill à la forme
  TanStack useQuery (data + isPending/isSuccess…), en anticipation de la mise à jour
  prévue de useShape par NextGraph — distingue nativement sync-en-cours de vide.
  Déviation actuelle notée : readEntities/subscribeDocs/bumpRead côté app.
- ngSession : access-log ON par défaut (le toggle opt-in était fragile), opt-out via
  localStorage festipod.debug.accessLog=0 ; ligne de diagnostic au démarrage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Duchesne
2026-07-09 22:36:29 +02:00
parent 4c80ada3de
commit 2295af610a
2 changed files with 60 additions and 11 deletions
+10 -11
View File
@@ -10,25 +10,24 @@ import { configure } from "@ng-eventually/client/polyfill";
// SDK-shaped surface used by ngSession itself — taken from the lib, not @ng-org.
import { ng, init as initNgWeb, initNg as initNgSignals } from "@ng-eventually/client";
// DIAGNOSTIC (shared-wallet isolation): turn on the SDK's OFF-by-default access
// log to SEE every read/write prefixed by the active identity — the way to catch
// a doc read under the wrong identity in the REAL app (the e2e harness can't
// reproduce it — cross-invocation reads return nothing there). Runtime toggle, no
// rebuild: in the browser console run
// localStorage.setItem('festipod.debug.accessLog','1') // then reload
// (unset / '0' turns it off). Also honoured: window.__FESTIPOD_ACCESS_LOG__.
// DIAGNOSTIC (shared-wallet isolation): the SDK access log SEES every read/write
// prefixed by the active identity — the way to catch a doc read under the wrong
// identity in the REAL app. Now ON BY DEFAULT (the opt-in toggle was fragile /
// easy to miss). To silence: in the browser console run
// localStorage.setItem('festipod.debug.accessLog','0') // then reload
function accessLogEnabled(): boolean {
try {
if (typeof localStorage !== "undefined"
&& localStorage.getItem("festipod.debug.accessLog") === "1") return true;
&& localStorage.getItem("festipod.debug.accessLog") === "0") return false;
} catch { /* storage may be unavailable */ }
return typeof window !== "undefined"
&& (window as unknown as Record<string, unknown>).__FESTIPOD_ACCESS_LOG__ === true;
return true;
}
const __accessLogOn = accessLogEnabled();
console.log("[NG session] access-log:", __accessLogOn ? "ON" : "OFF (localStorage festipod.debug.accessLog=0)");
configure({
ng: realNg, useShape: realUseShape, init: realInit, initNg: realInitNg,
debugAccessLog: accessLogEnabled(),
debugAccessLog: __accessLogOn,
});
export let session: NextGraphSession | undefined;