# Migration guide — when real NextGraph matures The whole point of this library: the consumer already writes SDK-shaped code, so when NextGraph ships cross-wallet reads, capabilities and inboxes, **only this lib changes**. The consumer's application code does **not** change. This is the checklist. ## Guiding invariant Every emulated piece has a 1:1 image in the real infra. Migration = swap the emulation for the real primitive, remove the scaffold. If a piece of the emulation has no clear target image, that is a drift signal (see [`simulation.md`](./simulation.md)). ## Checklist ### 1. Emulated ReadCaps → real capabilities Translate the per-document `CapRegistry` (`caps.ts`) into real NextGraph caps: the broker/verifier enforces them, and `useShape` already returns only authorized documents. The read filter (`read-filter.ts`) and the write guard (`ng-proxy.ts` `sparql_update` override) are then **dead code** — remove them. The access unit is already the document (`@graph`), matching the native per-repo cap model, so this is a data step, not a reshape. ### 2. Place documents in real native stores Today `docCreate(..., undefined)` writes every document into the shared wallet's **private** store, and the `public|protected|private` scope is a **logical label** in the shim (see the two-axes section in [`simulation.md`](./simulation.md)). - **`doc_create` cannot target a non-private native store today** — verified: `StoreRepo` is **not JS-constructible** from the SDK, so there is no way to pass a public/protected store as the create destination (`docCreate`'s trailing `store` arg is left `undefined` → private store). The private store works only because it opens without `RepoNotFound`. - When the SDK lets you construct/target a native store, the migration adds a `getNativeStore(scope)`-style resolver returning the real store to pass as the `docCreate` destination, so the logical scope label becomes a real store placement. (No such helper exists yet — it is blocked on the SDK gap above.) - At that point `store-registry.ts` maps `(account, scope)` to the user's **real store NURI** instead of a document in the shared wallet; the per-scope index document (the store-container emulation) is replaced by the store itself. The consumer-facing surface (`createEntityDoc`, `listEntityDocs`, resolvers) is designed to survive that swap unchanged. ### 3. Drop the resolver / shim The `sharedWalletShim` (account → 3 scope-document NURIs, RDF in the private store) has **no target equivalent** — the target has no central directory. Remove it: `store-registry.ts`, `configureStoreRegistry`, the shim SPARQL. Cross-wallet reads replace the fan-out; per-user wallets replace the shared one. ### 4. Real inbox → drop the emulated curator Replace the emulated `inbox.ts` deposit (`docs.sparqlUpdate` into a shared-wallet document) with the native `inbox_post_link`, and move `read`/`materialize`/`watch` to a **separate curator package** (the deferred global-index curator — see the top-level README and [`decisions/discovery-model.md`](./decisions/discovery-model.md)). The in-client read side goes away. The single global index replaces the cross-account fan-out. ### 5. Faux login → real per-user login Remove `accounts.ts` (the username `localStorage` faux login) and the app-level "Connexion" screen. The technical broker gate **becomes** the real per-user login (see [`decisions/shared-wallet-login-flow.md`](./decisions/shared-wallet-login-flow.md)). The flow shape ("broker redirect → app") does not change. ### 6. Drop the isolation scaffold `isolation.ts` (application social-visibility filter) disappears against a different piece of infra than the caps: real per-account wallets + a real per-account social graph. Distinct axis from ReadCaps — remove independently. ### 7. Remove the build alias — the client becomes the real SDK The consumer imports `@ng-org/web` / `@ng-org/orm` resolved to this lib via a **build alias** during the polyfill period. Removing the alias makes those imports resolve to the real SDK — the `ng`/`useShape`/`inbox` surface is SDK-identical, so **no consumer code changes**. The one non-SDK call — `configure(...)` / `@ng-eventually/client/polyfill` — is deleted. The lib itself disappears. ## What does NOT change **The consumer's application code.** Shapes, screens, the *acts* of granting access, entity→scope mapping, the connection graph — all injected, all untouched. Migration is entirely inside this library plus removing the alias + the bootstrap call. That asymmetry — a mature SDK face outward, all compensation inward — is the library's reason to exist.