refactor(vocabulary): les noms publiés parlent la langue de la cible, et un test le tient
La correction de nomenclature du 2026-07-30 — en amont un *wallet* n'est qu'un trousseau, ce qui possède des stores est un **user** (un *site*) — s'était faite à la main. `walletInbox` y a échappé et a vécu des semaines, en faisant des dégâts : le nom rendait « une inbox par wallet » évident, masquant qu'un user en a **deux** en amont (repos de store public et protected, les deux seuls `AddInboxCap` du moteur). Une discipline appliquée à la main en oublie un ; un test non. D'où `test/vocabulary.test.ts` : tout nom publié est bâti sur des mots que la CIBLE emploie — vérifiés dans `nextgraph-rs` — ou porte un marqueur disant POURQUOI il n'existe qu'ici (`virtual`, `physical`, `shim`, `emulated`, `polyfill`), ce qui dit aussi quand il disparaît. Un échec n'est pas « renommer pour faire passer le test », c'est une question : la cible a-t-elle un mot pour ça ? la chose n'existe-t-elle qu'ici ? le mot est-il vraiment de la glue ? Ce que le test a trouvé, et les réponses : - `walletInbox` → `userInbox`, avec l'écart de cardinalité écrit noir sur blanc plutôt que caché par le nom. - `accounts` / `AccountRecord` / `AccountStorage` → `virtualUsers` / `VirtualUserRecord` / `VirtualUserStorage`, module `accounts.ts` → `virtual-users.ts`. « account » n'est pas de la cible : c'est notre mot pour l'utilisateur virtuel, et le marqueur le dit désormais. - `readModel` → la fonction `readUnion`, exposée directement. « model » n'était ni de la cible ni de la glue, et le namespace ne tenait qu'une fonction. - Le reste était du vocabulaire légitime à déclarer (`subject`, `base`, `schema`, `connected`, le modèle réactif de l'ORM). Corrigé au passage, sur signalement du contrat interne : l'en-tête d'`open-repo` justifiait son correctif par un mécanisme que le source contredit. Un repo absent de `self.repos` lève bien `RepoNotFound` (`engine/verifier/src/request_processor.rs:264,269`). Les 0 lignes observées viennent d'ailleurs — `Verifier::load` repeuple `self.repos` depuis le stockage sur un profil persistant (`verifier.rs:535-560`), et notre propre `readDoc` attrape toute erreur et rend `[]`. Le correctif est bon, le diagnostic écrit à côté ne l'était pas. 159 tests unitaires, typecheck src/test/e2e vert, e2e 40/40 contre le broker.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
> And four more, all confirmed:
|
||||
>
|
||||
> 4. **D4 would delete a working recovery path.** Inbox deposits are never removed (`packages/client/src/surface/inbox.ts`), so a second device/tab recovers its caps by re-reading. localStorage-without-re-reading loses them permanently, and contradicts P1a's delivered doctrine that per-process rebuild "is correct".
|
||||
> 5. **D3 is false outside entity documents.** `capFor(scopeIndexDoc)` and `capFor(walletInbox)` are undefined before *and after* `listMyEntityDocs` — their caps can only ever be derived. Yet the boundary brief requires them reachable. Upstream that root comes from the wallet plus `AddSignerCap` on the User branch — a level the fact table omitted entirely.
|
||||
> 5. **D3 is false outside entity documents.** `capFor(scopeIndexDoc)` and `capFor(userInbox)` are undefined before *and after* `listMyEntityDocs` — their caps can only ever be derived. Yet the boundary brief requires them reachable. Upstream that root comes from the wallet plus `AddSignerCap` on the User branch — a level the fact table omitted entirely.
|
||||
> 6. **`doc_create` writes four times, not two** (+ the class quad on the Header branch, + `AddSignerCap` on the User branch).
|
||||
> 7. **Ordering defect: D2 before the boundary guard opens cap harvesting.** Once caps are triples in `scopeIndexDoc(bob,…)`, and both `scopeIndexDoc` and `docs.sparqlQuery` are exported, `setCurrentUser("mallory")` reads Bob's caps. Today `mintCap` is unexported, so a NURI yields nothing. **The guard must land before the caps become triples.**
|
||||
>
|
||||
@@ -69,7 +69,7 @@ All read in `nextgraph-rs` (`git 213338f6`) on 2026-07-30, recorded in full in [
|
||||
| scope index / scope container (`scopeIndexDoc`, `readScopeIndex`, `indexDocOf`, `INDEX_SUBJECT`) | **store** (`storeDoc`, `readStore`, …) | the thing that lists a user's documents IS a store |
|
||||
| `shim:contains` | `ldp:contains` | NextGraph's own predicate for exactly this |
|
||||
|
||||
`docPublic` / `docProtected` / `docPrivate` on `AccountRecord` already read as stores; keep them, or rename to `publicStore` / `protectedStore` / `privateStore` for symmetry.
|
||||
`docPublic` / `docProtected` / `docPrivate` on `VirtualUserRecord` already read as stores; keep them, or rename to `publicStore` / `protectedStore` / `privateStore` for symmetry.
|
||||
|
||||
### D2 — Emulate the Store branch as a distinct SUBJECT, not a distinct graph or document
|
||||
|
||||
@@ -93,7 +93,7 @@ The in-memory `CapRegistry` then stops being "the keyring" and becomes what it a
|
||||
|
||||
Verified: there is no received-caps register upstream, and inventing one would expose a shape the target does not have. What upstream does is persist the `read_cap` of every **opened** repo in local user storage.
|
||||
|
||||
So the emulation is a **local, per-virtual-user store** — the same nature as `shared-wallet/accounts.ts`'s existing `IdentityStore` (localStorage). This ends "re-read the inbox every session to recover caps", which the PO identified as the wrong model: an inbox is a queue you consume, not a store you re-read.
|
||||
So the emulation is a **local, per-virtual-user store** — the same nature as `shared-wallet/virtualUsers.ts`'s existing `IdentityStore` (localStorage). This ends "re-read the inbox every session to recover caps", which the PO identified as the wrong model: an inbox is a queue you consume, not a store you re-read.
|
||||
|
||||
*Open*: whether to do D4 in this lot or after the boundary lot. It is the piece with the most design risk, and it is not needed for D1–D3 to be correct.
|
||||
|
||||
@@ -106,7 +106,7 @@ So the emulation is a **local, per-virtual-user store** — the same nature as `
|
||||
|
||||
## What this breaks
|
||||
|
||||
`storeRegistry`'s exported names change (`scopeIndexDoc`, `listEntityDocs`, `AccountRecord` fields). `shim:contains` becomes `ldp:contains`, so **existing dev wallets stop resolving their documents** — acceptable for dev data, and consistent with how the pointer/doc-shim migration was handled before, but it must be stated rather than discovered.
|
||||
`storeRegistry`'s exported names change (`scopeIndexDoc`, `listEntityDocs`, `VirtualUserRecord` fields). `shim:contains` becomes `ldp:contains`, so **existing dev wallets stop resolving their documents** — acceptable for dev data, and consistent with how the pointer/doc-shim migration was handled before, but it must be stated rather than discovered.
|
||||
|
||||
## Risks I want challenged
|
||||
|
||||
|
||||
Reference in New Issue
Block a user