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.4 KiB
Vision & principles of the @ng-eventually/sdk polyfill
Purpose
A stand-in faithful in SHAPE to NextGraph's future primitives. Single objective: that consumers (Festipod) be coded against the CORRECT mental model — the one of finished NextGraph — and have NOTHING to rewrite when NextGraph provides the real primitives.
What the polyfill is NOT
A security layer. The shared wallet (everyone shares the same keys) plus the absence of real crypto make the emulation infinitely less secure than a wallet-per-user — it is a dev/staging vehicle, not a goal. Insecurity is ACCEPTED. An attacker who bypasses the emulation is not our problem.
The only criterion: shape-fidelity, with RIGOR
The exposed surfaces must match the exact SHAPE of the future primitives, even where enforcement is simulated. The failure mode to avoid: exposing the wrong shape → the consumer codes against a model that will not exist → rewrite. The ACL inversion of ReadCaps was exactly that defect (an ACL where the real thing is key possession) — a lack of rigor.
Simulating crypto to PREVENT shortcuts
Without a minimum of crypto simulation, damaging shortcuts get taken (reading the plaintext, falling back on ACLs). The polyfill therefore simulates the final mechanism, enough to hold this invariant:
A
did(bare id, WITHOUT a ReadCap) and a NURI (WITH a ReadCap) are treated GENUINELY differently: the former does NOT allow reading the data; the latter is SUFFICIENT and REQUIRED.
Concretely, in the target: a document's data is stored encrypted (per-doc symmetric encryption, however lightweight); the ReadCap = the key; without it, decrypting/reading is impossible. No ACL, no plaintext accessible "on the side". Obtaining read access = holding the key, exactly as in the target model.
Not yet true here, and saying so matters. The shape is in place — possession decides, every access is confined to the connected virtual user, caps are stored and read back — but the cap value is the constant
OKand nothing is encrypted. Per-document encryption is P1b, and it is one function (nuri.tsmintCap). Until it lands, nothing this library does may be described as anonymous or private.
Shape consequences (to respect everywhere)
- Everything is keys and URLs. There is no notion of membership, role, or authorization list in the model: only symmetric and asymmetric cryptography, URIs, and who holds which key. Any exposed shape that looks like an ACL, a
member, arole, or apermissionis a wrong shape, whatever scaffolding one may otherwise read in the current state of NextGraph. - Reading = possession of the read key (ReadCap =
{id, key}). A bare id (adidwithout a ReadCap) does not read. - Writing = possession of the write key — a key distinct from the read key, hence a distinct axis, but possession too.
- Sharing a cap = sealing it to a recipient (durable delivery, at share time — NOT an ACL re-declared every session).
- Revocation = re-key (new key; former holders keep the old state). Non-retroactive.
- Cap-less reference (naming/pointing without reading) distinct from the cap-bearing reference.
See readcap-and-nuri-model.md (the real model, verified in nextgraph-rs) and briefs/2026-07-20-caps-emulation-alignment.md (the alignment effort).