# ADR — Use a store NURI as the `useShape` scope AND `@graph` **Date:** 2026-03-17 · **Status:** Accepted (partially superseded — see below). Historical decision, ported into this lib because the *insight* still governs how the shim opens repos. Original context: the consuming app. > **Partially superseded (2026-07-03).** The private-store-only scope was replaced > for shareable domain entities: they are now scoped AND written to the > **protected** store (`did:ng:${protected_store_id}`), verified to open without > `RepoNotFound`. **The central insight of this ADR still holds** and now applies > to **both** stores: you must open the repo via the store's NURI > or you get `RepoNotFound`. *(How it is opened has since changed — see the note > under Decision.)* ## Context Loading test data updated the in-memory ORM signals (immediate UI) but produced `RepoNotFound` on `doc_create` and `orm_frontend_update`. Data vanished on reload because the SPARQL writes never reached the broker: the verifier's `self.repos` HashMap did not contain the store's repo → `resolve_target()` failed. ## Options considered ### A — `did:ng:i` scope + `doc_create` for `@graph` `did:ng:i` is documented as a subscription scope; `doc_create` returns a real NURI. **Against:** `did:ng:i` goes through `NuriTargetV0::UserSite`, which does NOT open individual repos; `doc_create` calls `resolve_target(PrivateStore)`, which requires the repo already in `self.repos` → fails; needs complex retry/timing. ### B — the store NURI as scope AND `@graph` (chosen) Exact copy of the working `expense-tracker-rdf` example: `orm_start_graph` with the store's NURI opens the repo in `self.repos`; subsequent `orm_frontend_update` finds it. Simple, no retry. **Against:** slightly less flexible than `did:ng:i` (scoped to one store); requires passing the session down to the ORM hook. ### C — `did:ng:i` scope + reuse an existing entity's `@graph` Works for users who already have data. **Against:** fails for empty wallets (no entity to reuse) → falls back to `doc_create` and the same `RepoNotFound`. ## Decision **Option B**: use the store NURI as both the `useShape` scope AND the write `@graph`, exactly like `expense-tracker-rdf`. This is why this lib's shim opens the store repo before writing, and why **`did:ng:i` must never be used as a scope** (it breaks writes with `RepoNotFound`). See the scope rule in [`../simulation.md`](../simulation.md). *The decision stands; the mechanism named in it has been replaced.* Opening was `orm_start_graph` when this was written. It is now `ensureRepoOpen` — `doc_subscribe` plus a wait for the first `State` (`packages/client/src/open-repo.ts:167`) — after `orm_start_graph` was found to hang on a fan-out (`subscribe.ts:28,181`). What must be read here is the invariant *"open the repo, by its store NURI, before writing"*, not the call that used to implement it. ## Consequences - **Positive:** immediate writes after connect (no retry); persistence across reload; aligned with the official examples. - **Risk:** if NextGraph changes the store's open behaviour, this breaks.