fix(client): durcir le cold-start du shim — ensureRepoOpen(anchor) avant lecture/écriture
Défensif : loadShim/resolveAccount/ensureAccount ouvrent l'anchor (private-store-root) avant de lire/écrire le compte shim, comme le fait déjà readScopeIndex. Robustesse same-session si l'anchor est là-mais-pas-encore-souscrit. NB (vérifié nextgraph-rs) : sur le login broker normal, le bootstrap charge le private-store dans self.repos AVANT de rendre la session à JS → un wallet FRAIS retourne 0 rows (pas RepoNotFound) et provisionne. Il n'existe AUCUN primitif JS pour ouvrir un repo *inconnu* : ce heal n'est pas un remède à un store non bootstrappé (limite NextGraph), juste une robustesse d'ouverture same-session. Tests : cold-start-anchor.test.ts (rouge-avant/vert-après unit) ; harness e2e repro-fresh-wallet (mint un wallet neuf par run — comble le trou "aucun test de démarrage à froid sur wallet vierge"). Fakes anti-fork/watch-shape honorent désormais la barrière first-State dont dépend le heal. e2e réel 42/42. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -235,6 +235,10 @@ export async function loadShim(): Promise<Map<string, AccountRecord>> {
|
||||
}
|
||||
}`;
|
||||
const map = new Map<string, AccountRecord>();
|
||||
// COLD-START heal: open the anchor (private-store-root) repo before the shim scan,
|
||||
// so an anchored read on a fresh wallet whose anchor repo isn't yet in `self.repos`
|
||||
// resolves instead of throwing `RepoNotFound`. Idempotent; see resolveAccount.
|
||||
await ensureRepoOpen(anchor);
|
||||
try {
|
||||
const result = await sparqlQuery(s.sessionId, query, undefined, anchor, "loadShim");
|
||||
// Group ALL bindings by account key first, then pick the CANONICAL doc per
|
||||
@@ -281,6 +285,21 @@ export async function resolveAccount(id: string): Promise<AccountRecord | null>
|
||||
|
||||
const s = await session();
|
||||
const anchor = await anchorNuri();
|
||||
// COLD-START heal (polyfill-era): the shim lives in the private-store-root graph
|
||||
// (the anchor). An anchored `sparql_query` on a repo absent from the verifier's
|
||||
// `self.repos` throws `RepoNotFound` — a HARD error here, unlike per-entity docs
|
||||
// which silently read 0 (the private/store target resolves through
|
||||
// `resolve_target_for_sparql`, which requires the repo loaded). Open the anchor
|
||||
// ONCE before reading, idempotently — the SAME open-before-read guard
|
||||
// `readScopeIndex` applies to its index doc. NB (see docs/nextgraph-current-state):
|
||||
// `ensureRepoOpen` (→ `doc_subscribe`) can only OPEN/subscribe a repo the session
|
||||
// ALREADY holds; it cannot pull a genuinely-absent repo (no JS primitive does). On
|
||||
// the real broker the private-store repo is bootstrapped into `self.repos` at
|
||||
// connect, so this is a defensive same-session open — it makes the anchor read/write
|
||||
// robust to a not-yet-subscribed anchor without ever being able to hide a truly
|
||||
// unbootstrapped store. No-op with the unit fake ng and when the repo is already
|
||||
// open. See open-repo.ts.
|
||||
await ensureRepoOpen(anchor);
|
||||
// `subj` is already IRI-safe (accountSubject → escapeIri); `anchor` is a
|
||||
// trusted-shaped NURI → assertNuri. The query is bounded to this one subject.
|
||||
const subj = accountSubject(id);
|
||||
@@ -443,6 +462,13 @@ export async function ensureAccount(id: string): Promise<AccountRecord> {
|
||||
|
||||
const s = await session();
|
||||
const anchor = await anchorNuri();
|
||||
// COLD-START heal: open the anchor (private-store-root) repo before PROVISIONING
|
||||
// into it. The provision `sparqlUpdate` targets the private-store graph, which
|
||||
// resolves through the same repo-loaded requirement — an unopened anchor repo on
|
||||
// a fresh wallet would throw `RepoNotFound` and the account would never persist.
|
||||
// Idempotent; a no-op once the repo is open (resolveAccountReliably already
|
||||
// opened it on the read above in the common path). See open-repo.ts.
|
||||
await ensureRepoOpen(anchor);
|
||||
const subj = accountSubject(id);
|
||||
// `subj` is already IRI-safe (accountSubject → escapeIri). `anchor` is a
|
||||
// trusted-shaped NURI → assertNuri. `id` is UNTRUSTED text in a LITERAL
|
||||
|
||||
Reference in New Issue
Block a user