feat(client): read via per-doc ANCHORED queries; document virtual vs physical wallet
The anchorless union query (`GRAPH ?g`) scanned EVERY named graph in the local
store (the whole shared physical wallet) → O(wallet size), slow/timeouts on a
bloated wallet. Rewrite `readUnion` to run ONE ANCHORED `sparql_query` per by-need
doc (in parallel, per-doc tolerant): an anchored query is restricted to that
repo's graph, so it is O(1) per doc, INDEPENDENT of physical-wallet size. Keep the
ReadCap defense-in-depth gate.
docs/simulation.md: new "Physical wallet vs virtual wallet" section — the physical
shared wallet is a substrate that accumulates and must NEVER be enumerated/scanned;
each user's VIRTUAL wallet (the account's scope index in the shim) is the bounded
thing you enumerate ("list my documents"), then read those docs per-doc anchored.
read-model.md / nextgraph-current-state.md updated to the per-doc anchored rule.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -191,14 +191,23 @@ from JS today a repo becomes queryable ONLY by being `doc_create`d in this sessi
|
||||
|
||||
**Consequence for this lib's mono-wallet polyfill:** every account's documents are
|
||||
`doc_create`d in the ONE shared wallet within the SAME session, so they are ALL
|
||||
already in `self.repos` and queryable by the anchorless union **without any per-doc
|
||||
open step**. `read-model.ts`'s per-doc anchored `ASK` is therefore a *no-op* on a
|
||||
present repo and an instant `RepoNotFound` skip on an absent one — it never SYNCS
|
||||
(it cannot). The union query alone spans all same-session repos. At the real
|
||||
multi-store migration this gap closes: opening a real per-user store repo by cap is
|
||||
a native broker sync (the `OpenRepo` TODO at `verifier.rs:1423`), and the open step
|
||||
becomes a real sync. Opening still requires the repo's **NURI + ReadCap** — there is
|
||||
**no store-level read inheritance** (see § Capability / ReadCap granularity).
|
||||
already in `self.repos`. `read-model.ts` reads the **bounded, by-need** set of docs
|
||||
with ONE **anchored** `sparql_query` per doc (`SELECT ?s ?p ?o WHERE { ?s ?p ?o }`,
|
||||
anchor = the doc NURI): the anchor resolves that same-session repo directly (no
|
||||
separate open needed) and restricts the query to its graph → O(1) per doc,
|
||||
independent of the store's size. An absent repo throws `RepoNotFound` on its own
|
||||
read and is skipped, never aborting the batch.
|
||||
|
||||
**Do NOT anchorless-union-scan on the read path.** An anchorless
|
||||
`SELECT … WHERE { GRAPH ?g { ?s ?p ?o } }` spans EVERY named graph in the store —
|
||||
O(wallet size). On a **shared / bloated** wallet that accumulates docs across runs
|
||||
that was O(wallet) and timed out (~90s observed on `readUnion` / probe reads). The
|
||||
per-doc anchored read makes a non-empty wallet irrelevant. At the real multi-store
|
||||
migration this is unchanged (the anchored read is native); only bringing a repo into
|
||||
the session changes: opening a real per-user store repo by cap becomes a native
|
||||
broker sync (the `OpenRepo` TODO at `verifier.rs:1423`). Opening still requires the
|
||||
repo's **NURI + ReadCap** — there is **no store-level read inheritance** (see
|
||||
§ Capability / ReadCap granularity).
|
||||
|
||||
### The union is READ-ONLY — writes must target one document
|
||||
|
||||
|
||||
Reference in New Issue
Block a user