WIP: open/subscribe repos before anchored cold-start reads (branche, non mergée)
Défaut visé : sur une session verifier fraîche (reconnexion), la lecture ancrée tape des repos pas encore ouverts dans self.repos → 0 ligne. Nouveau module `open-repo.ts` : `ensureReposOpen`/`ensureRepoOpen` ouvrent/souscrivent un repo via la primitive existante `subscribeDoc` (doc_subscribe) et attendent le push d'état initial (borné, sans polling) AVANT la lecture ancrée. Câblé en amont de `readUnion` (read-model) et `readScopeIndex` (store-registry). Idempotent par session (Set des NURI ouverts + Map in-flight ; ré-ouverture si la session injectée change). No-op si le `ng` injecté n'a pas doc_subscribe (fake unitaire). État — NON MERGÉ, incomplet : - AIDE le PROTECTED : la participation remonte au cold-start (mesuré app, timing un peu bruité). - N'ADRESSE PAS l'accueil PUBLIC : `readScopeIndex` de l'index public rend 0 même côté écrivain même-session — le fix ouvre le repo mais l'index reste vide. Le code d'index lib est prouvé scope-symétrique, donc la cause du public est ailleurs (broker/store ou chemin app), À MESURER SOUS BROKER (actuellement injoignable). Nécessité du fix elle-même non prouvée en e2e lib (broker down). gate broker-indépendant : tsc --noEmit propre ; bun test 91 pass (worker). Inclut le scaffolding e2e de repro reconnexion (broker/run/sdk-entry). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import { chromium, type BrowserContext, type Page, type Frame } from "playwright
|
||||
import { execSync } from "node:child_process";
|
||||
import * as http from "node:http";
|
||||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
@@ -139,6 +140,46 @@ export async function launchWalletContext(): Promise<BrowserContext> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a persistent context on a FRESH, EMPTY profile dir (its own userDataDir).
|
||||
* Empty local storage ⇒ empty verifier repo cache ⇒ the reconnection cold-start:
|
||||
* the same wallet's repos are on the broker but NOT in this profile's IndexedDB, so
|
||||
* a session over it starts with an empty `self.repos`. Caller must import the wallet
|
||||
* (see {@link importWalletViaFile}) before opening the SDK page. Returns the context
|
||||
* and the dir so the caller can clean it up.
|
||||
*/
|
||||
export async function launchCleanProfileContext(): Promise<{ ctx: BrowserContext; dir: string }> {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "ng-eventually-clean-"));
|
||||
const ctx = await chromium.launchPersistentContext(dir, {
|
||||
headless: true,
|
||||
executablePath: resolveChromePath(),
|
||||
args: LAUNCH_ARGS,
|
||||
});
|
||||
return { ctx, dir };
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a `.ngw` wallet FILE into the current (clean) profile via the standalone
|
||||
* nextgraph.eu "Import a Wallet File" flow, then unlock it with the password. After
|
||||
* this the profile holds the wallet — but NOT the repos' local cache — so the next
|
||||
* SDK session over it hits the broker-only cold-start. Adapted from the Festipod
|
||||
* app's `importWalletViaFile` (the proven real-broker wallet-file import).
|
||||
*/
|
||||
export async function importWalletViaFile(page: Page, ngwPath: string): Promise<void> {
|
||||
await page.goto("https://nextgraph.eu/#/wallet/login", { waitUntil: "domcontentloaded" });
|
||||
// Let the SPA render + attach the file input (uploading too early → EncryptionError).
|
||||
await page.waitForTimeout(3000);
|
||||
await page.locator('input[type=file]').waitFor({ state: "attached", timeout: 15000 });
|
||||
await page.setInputFiles('input[type=file]', ngwPath);
|
||||
const passwordInput = page.locator('input[type=password]').first();
|
||||
await passwordInput.waitFor({ state: "visible", timeout: 15000 });
|
||||
await passwordInput.fill(WALLET_PASSWORD);
|
||||
await passwordInput.press("Enter");
|
||||
const confirm = page.getByRole("button", { name: /Confirm/i });
|
||||
if (await confirm.isVisible({ timeout: 2000 }).catch(() => false)) await confirm.click().catch(() => {});
|
||||
await page.waitForTimeout(8000); // unlock + verifier bootstrap from the broker
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate through the broker (nextgraph.net redirect) to load `appUrl` in the
|
||||
* broker iframe; unlock the dedicated wallet if a login is shown; return the app
|
||||
|
||||
Reference in New Issue
Block a user