feat(client): SDK-shaped scope resolvers (resolveScopeGraph/resolveInboxAnchor)
Expose a clean scope-based surface so consumers work by scope (public/protected/ private) and never see a physical store id — the library resolves placement and performs the shared-wallet simulation internally. RegistrySession gains optional protected/public store ids, supplied at the single injection point (configureStoreRegistry). Zero domain knowledge. docs/simulation.md updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,35 @@ The `store≠document` two axes materialize here directly: the registry moves al
|
||||
axis B (more documents = more isolation), never axis A (it always writes into the
|
||||
one private store via `docCreate(..., undefined)`).
|
||||
|
||||
### SDK-shaped scope resolvers — the consumer holds NO store-id
|
||||
|
||||
The consumer must never construct a `did:ng:${store_id}` NURI itself: physical
|
||||
placement is the lib's job (the whole point of the SDK boundary). Two resolvers
|
||||
turn a **logical scope** into an **opaque graph NURI** without exposing any
|
||||
store-id:
|
||||
|
||||
- **`resolveScopeGraph(scope)`** — the graph where the current session writes
|
||||
entities of `scope`, and whose repo `useShape` subscribes to read them back.
|
||||
Use the returned value as BOTH the read scope (`useShape(shape, nuri)`) and the
|
||||
`@graph` write target. Placement lives HERE (Axis A): `private` → the private
|
||||
native store; `public` + `protected` → the **protected** native store, because
|
||||
`doc_create`/ORM cannot target a non-private/protected native store today (SDK
|
||||
blocker, [`migration-guide.md`](./migration-guide.md)). At migration each scope
|
||||
resolves to the user's REAL per-scope store — the change is in this function,
|
||||
the consumer is unchanged.
|
||||
- **`resolveInboxAnchor()`** — the anchor where emulated inbox deposits land
|
||||
(today the shared wallet's private store — a real repo NURI, required because
|
||||
the broker rejects a `urn:` anchor). At migration it becomes the host's native
|
||||
inbox NURI.
|
||||
|
||||
Both resolve the native store ids from the **injected session**
|
||||
(`RegistrySession.protectedStoreId` / `publicStoreId`, alongside the existing
|
||||
`privateStoreId` anchor). The consumer hands the whole session to the lib at the
|
||||
ONE injection point (`configureStoreRegistry({ getSession })`) — that is wiring,
|
||||
not placement logic; everything else in the consumer speaks only in scopes. If
|
||||
the session omits `protectedStoreId`, the non-private scopes fall back to the
|
||||
private store rather than emit a broken NURI.
|
||||
|
||||
## `RepoNotFound` and the `orm_start_graph` scope rule
|
||||
|
||||
A hard constraint inherited from the SDK: to read **and** write entities through
|
||||
|
||||
Reference in New Issue
Block a user