feat(client): union-read ReadCap gate + listMyEntityDocs + doc corrections
- read-model.ts `readUnion` now applies the emulated ReadCap gate (drops a
subject when its doc is governsRead && !canRead for the current identity), so
per-scope isolation holds by construction AND by filter.
- store-registry: `listMyEntityDocs(username, scope)` (current account only) vs
the all-accounts `listEntityDocs` fallback (documented as the enumeration to
avoid on the read path).
- docs: nextgraph-current-state / read-model — corrected to the SOURCE-VERIFIED
reality that the JS SDK exposes NO open/sync-by-cap primitive
(load_repo_from_read_cap is pub(crate)); in the mono-wallet all repos are
already local (same session), so the anchorless union spans them with no open
step. simulation.md: listEntityDocs+useShape({graphs}) is a fallback, not the
read path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -176,13 +176,29 @@ and the web variant at ~`553-610`) reads the target from the `nuri` arg: a strin
|
||||
|
||||
A repo's triples enter `graph_dataset` (hence the union) only after the repo is
|
||||
opened/synced into `self.repos` **and** its commits applied via `update_graph`.
|
||||
Paths that open a repo: `doc_create` (own docs), bootstrap /
|
||||
`load_repo_from_read_cap`, or being followed from a store's `ldp:contains` / a
|
||||
shared cap / an inbox. Opening requires possessing the repo's **NURI + ReadCap** —
|
||||
there is **no store-level read inheritance** (see § Capability / ReadCap
|
||||
granularity). *(INFERRED: that "following a graph reference makes a previously
|
||||
unknown repo known/openable" is the one step not read verbatim in source; the
|
||||
open-requires-cap and no-inheritance facts around it ARE verified.)*
|
||||
|
||||
**VERIFIED (T03.k) — there is NO JS primitive to sync an *unknown* repo.** Every
|
||||
JS entry point that could "open" a repo — `sparql_query` anchored,
|
||||
`doc_subscribe` (`Fetch::Subscribe`), `orm_start_graph` — resolves its target via
|
||||
`resolve_target`/`resolve_target_for_sparql`, which does
|
||||
`self.repos.get(repo_id).ok_or(RepoNotFound)` (`request_processor.rs:155/163/264/269`).
|
||||
None of them PULLS a repo that is absent from `self.repos`; they only touch a repo
|
||||
already there. The primitive that actually loads a repo from its ReadCap,
|
||||
`Verifier::load_repo_from_read_cap` (`verifier.rs:2237`), is **`pub(crate)` —
|
||||
unexposed to JS**; it is only reached internally (bootstrap, inbox processing). So
|
||||
from JS today a repo becomes queryable ONLY by being `doc_create`d in this session
|
||||
(own docs) or synced by an internal path — never on demand by NURI+ReadCap.
|
||||
|
||||
**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).
|
||||
|
||||
### The union is READ-ONLY — writes must target one document
|
||||
|
||||
|
||||
Reference in New Issue
Block a user