diff --git a/packages/client/src/emulated-verifier/connect.ts b/packages/client/src/emulated-verifier/connect.ts index 98ace7b..a3befdb 100644 --- a/packages/client/src/emulated-verifier/connect.ts +++ b/packages/client/src/emulated-verifier/connect.ts @@ -34,7 +34,7 @@ * them and this drains each in turn. */ -import { getCaps, getCurrentUser } from "../polyfill"; +import { getCaps, getCurrentUser } from "../shared-wallet/bootstrap"; import { myInboxes, readLinks, resolveAccount } from "../shared-wallet/account-registry"; import { processInbox } from "../surface/inbox"; diff --git a/packages/client/src/emulated-verifier/open-repo.ts b/packages/client/src/emulated-verifier/open-repo.ts index a0525ba..e6fa613 100644 --- a/packages/client/src/emulated-verifier/open-repo.ts +++ b/packages/client/src/emulated-verifier/open-repo.ts @@ -60,7 +60,7 @@ */ import { mustNotAttempt } from "./reach"; -import { getConfig, getStoreRegistryDeps } from "../polyfill"; +import { getConfig, getStoreRegistryDeps } from "../shared-wallet/bootstrap"; import { subscribeDocUnguarded, type Unsubscribe } from "../surface/subscribe"; import { logStage, shortNuri } from "../shared-wallet/access-log"; import type { Nuri } from "../model/types"; diff --git a/packages/client/src/emulated-verifier/reach.ts b/packages/client/src/emulated-verifier/reach.ts index d7d0e72..83b2d39 100644 --- a/packages/client/src/emulated-verifier/reach.ts +++ b/packages/client/src/emulated-verifier/reach.ts @@ -40,7 +40,7 @@ * At migration this module disappears: the boundary becomes the wallet itself. */ -import { getCaps } from "../polyfill"; +import { getCaps } from "../shared-wallet/bootstrap"; import { targetOf } from "../model/nuri"; import type { Nuri } from "../model/types"; diff --git a/packages/client/src/polyfill.ts b/packages/client/src/polyfill.ts index 90b08ef..49f6e48 100644 --- a/packages/client/src/polyfill.ts +++ b/packages/client/src/polyfill.ts @@ -1,223 +1,32 @@ /** - * The polyfill bootstrap — the ONLY non-SDK surface of the client. + * `@ng-eventually/client/polyfill` — the polyfill-era door. * - * It injects the REAL SDK and the polyfill settings; afterwards the SDK-shaped - * exports (`ng`, `useShape`, `inbox`) behave as drop-ins. This is exposed at the - * subpath `@ng-eventually/client/polyfill` so the main entry - * (`@ng-eventually/client`) stays a **pure, SDK-identical** surface. Everything - * here is removed at migration. - */ - -import type { NgLike, UseShapeLike, Nuri, PrincipalId, ReadCap } from "./model/types"; -import type { RegistrySession } from "./shared-wallet/account-registry"; -import { CapRegistry } from "./emulated-verifier/caps"; -import { setAccessLog } from "./shared-wallet/access-log"; -import { inspectOutbox } from "./shared-wallet/outbox-log"; -import { startConnect } from "./emulated-verifier/connect"; - -/** - * Consumer-injected dependencies of the storeRegistry (polyfill-era). The - * registry itself is generic (it knows only native scopes); the consumer wires - * up how to reach the shared-wallet session and how to normalize an identity id - * used as the shim key. Removed at migration along with the whole shim. - */ -export interface StoreRegistryDeps { - /** Resolve the current shared-wallet session (id + private-store anchor). */ - getSession: () => Promise; - /** Normalize an identity id for shim keying. Default: trim (identity-ish). */ - normalizeId?: (id: string) => string; - /** - * POINTER micro-guard budget. The account records now live in a subscribable - * doc-shim (`did:ng:o:...`) reached through a well-known write-once POINTER triple - * in the store-root graph. The doc-shim read is barrier-AUTHORITATIVE, so accounts - * need NO retry (this replaces the deleted account-level `provisionRetry`). The - * ONLY residual sync-lag window is the store-root pointer read itself — one - * write-once triple. This bounded guard re-reads JUST that pointer a few times if a - * fresh cold read misses it; it can never provision or fork an account (worst case: - * a couple extra reads before an existing pointer is seen). Enable it where the REAL - * broker is used (app + e2e). Left UNSET (the default) → `attempts: 1` = single - * read, keeping the synchronous unit fakes fast and unchanged. - */ - pointerGuard?: { attempts?: number; baseMs?: number; maxStepMs?: number }; -} - -export interface EventuallyConfig { - /** The REAL `@ng-org/web` `ng` (injected to avoid a hard import / alias loop). */ - ng: NgLike; - /** The REAL `@ng-org/orm` `useShape`. */ - useShape: UseShapeLike; - /** Shared-wallet credentials — polyfill only (one wallet for everyone). */ - sharedWallet?: { name: string; secret: string }; - /** Initial current user; may also be set later via {@link setCurrentUser}. */ - currentUser?: PrincipalId; - /** - * Turn on the OFF-by-default document access log (see {@link ./access-log}): - * every real read/write is printed, prefixed by the active identity, to - * diagnose the shared-wallet isolation leak. Also enablable without a code - * change via the env var `NG_EVENTUALLY_ACCESS_LOG=1`. Default: false. - */ - debugAccessLog?: boolean; - /** REAL `@ng-org/web` `init` (lifecycle) — forwarded by the lib's `init()`. */ - init?: (...args: any[]) => any; - /** REAL `@ng-org/orm` `initNg` (ORM signals) — forwarded by the lib's `initNg()`. */ - initNg?: (...args: any[]) => any; -} - -let cfg: EventuallyConfig | null = null; -let currentUser: PrincipalId | null = null; -/** Required fields of StoreRegistryDeps after defaults are applied. `pointerGuard` - * defaults to `{ attempts: 1 }` (single read) when the consumer leaves it unset. */ -type ResolvedRegistryDeps = Required< - Pick ->; -let registryDeps: ResolvedRegistryDeps | null = null; -/** - * The map key of the current identity — deliberately NOT the raw id. + * Everything importable here disappears at migration, and that is the point of the + * separate entry: what an application imports from this path is exactly what it will + * have to delete. The SDK-identical entry (`@ng-eventually/client`) carries the other + * promise — a target counterpart for every symbol. * - * A virtual user IS a shim account, and the shim keys accounts by the - * consumer-injected `normalizeId` ("@Alice" and "alice" are ONE account, with one - * set of scope documents). This record must key the same way, or a consumer that - * spells its own id differently between two calls gets a SECOND record and stops - * reading its own documents — the caps are filed under one spelling and looked up - * under the other. Falls back to the raw id while the registry deps are not yet - * configured (nothing can be filed before that anyway). + * This file only RE-EXPORTS. The implementation lives with the fate it belongs to: + * the injection store and the current-user relay in `shared-wallet/bootstrap.ts` + * (no counterpart, evaporates), the cap registry in `emulated-verifier/caps.ts` + * (stands in for the verifier's own bookkeeping). Keeping the store here made the + * published entry a dependency of the code it publishes. */ -function capsHolder(): PrincipalId | null { - if (currentUser === null) return null; - return registryDeps ? registryDeps.normalizeId(currentUser) : currentUser; -} -/** - * The emulated cap registry — one record PER identity (per virtual user), - * resolved through {@link capsHolder} on every call. So switching identity - * SWITCHES heldByHolder (nothing to reset, nothing wiped); see `caps.ts`. Empty until - * the first cap is issued, and while it is empty the read filter passes through - * (no regression). - */ -let caps = new CapRegistry(capsHolder); - -export function configure(c: EventuallyConfig): void { - cfg = c; - currentUser = c.currentUser ?? null; - setAccessLog(c.debugAccessLog ?? false); -} - -/** @internal — used by the SDK-shaped wrappers to reach the injected real SDK. */ -export function getConfig(): EventuallyConfig { - if (!cfg) throw new Error("[ng-eventually] configure() must be called before use"); - return cfg; -} - -/** Reset the injected config back to un-configured (mainly for tests, so a - * suite that calls configure() can restore the not-configured guard state). */ -export function resetConfig(): void { - cfg = null; - currentUser = null; -} - -/** - * Wire the storeRegistry's consumer-injected dependencies (session + identity-id - * normalization). Must be called before any storeRegistry.* use. Separate from - * {@link configure} because it's storeRegistry-specific and, like the shim, - * disappears at migration. - */ -export function configureStoreRegistry(deps: StoreRegistryDeps): void { - // Fire the outbox inspection (Volet 3 of the low-level data-path trace) once, - // on the FIRST successful `getSession()` resolution — the most reliable - // "a session is established" signal available: every low-level reader/writer - // (store-registry, open-repo, read-model, subscribe, inbox) reaches its - // session through this SAME injected `getSession`, so wrapping it HERE catches - // the first success from whichever caller happens to run first, instead of - // tying the probe to one particular call site. Only on SUCCESS (an error - // propagates untouched, exactly as before) and only ONCE per - // `configureStoreRegistry()` call (a fresh session config → a fresh check). - let outboxInspected = false; - const getSession = async (): Promise => { - const session = await deps.getSession(); - if (!outboxInspected) { - outboxInspected = true; - inspectOutbox(); - } - return session; - }; - registryDeps = { - getSession, - normalizeId: deps.normalizeId ?? ((id: string) => id.trim()), - // Default: single read (no re-read). Only the real-broker consumers (app + e2e) - // opt into the bounded pointer micro-guard; unit fakes stay synchronous. - pointerGuard: deps.pointerGuard ?? { attempts: 1 }, - }; -} - -/** @internal — used by the storeRegistry to reach its injected dependencies. */ -export function getStoreRegistryDeps(): ResolvedRegistryDeps { - if (!registryDeps) { - throw new Error("[ng-eventually] configureStoreRegistry() must be called before use"); - } - return registryDeps; -} - -/** Reset storeRegistry deps (mainly for tests). */ -export function resetStoreRegistry(): void { - registryDeps = null; -} - -/** - * Set the current identity id — who the SDK is reading/writing as. In the target - * this is the wallet user established at wallet-import time; here the consumer - * relays that id through this call so the read filter and the inbox `from` know - * who is acting. Passing `null` clears it (no identity yet, e.g. during startup). - */ -export function setCurrentUser(id: PrincipalId | null): void { - const changed = currentUser !== id; - currentUser = id; - // Connecting a user is what triggers inbox processing — the library's job, not - // the app's. Fire-and-forget: this setter is synchronous and every consumer calls - // it from synchronous code, so the work announces itself through the cap - // registry's change signal instead of making callers await. See `connect.ts`. - // - // Gated on the registry being configured, and that is not a test convenience: an - // identity set before the session resolves has nothing to restore and no inbox to - // reach, so firing would be I/O that can only fail. The consumer's real sequence - // is `configureStoreRegistry` then `setCurrentUser`; anything else can call - // `connectedUser()` explicitly. - if (changed && id !== null && registryDeps !== null) startConnect(); -} - -export function getCurrentUser(): PrincipalId | null { - return currentUser; -} - -/** The emulated cap registry — what the current identity holds, plus the emulated - * public store. The read filter and the read-model consult it. */ -export function getCaps(): CapRegistry { - return caps; -} - -/** - * Do I hold the cap of `nuri`? — the held-caps lookup, the ONLY way a cap is - * obtained besides being given one. Returns `undefined` when what I hold has none; - * that is the whole answer the model can give (there is no "may P read D?"). - * - * Shorthand for `getCaps().capFor(nuri)`, exposed because it is the surface the - * consumer actually uses. - */ -export function capFor(nuri: Nuri): ReadCap | undefined { - return caps.capFor(nuri); -} - -/** - * Drop EVERY holder's caps (tests / a fresh wallet). This is **not** what an identity - * change does: switching identity switches heldByHolder, it never wipes one — if it - * wiped, durability would be a lie and per-session re-declaration would come back - * under another name. Nothing in the library calls this on `setCurrentUser`. - */ -export function resetCaps(): void { - // Clear IN PLACE rather than rebuilding: whoever subscribed to the registry's - // change signal (`watchShape`) stays subscribed to the live instance instead of - // silently holding a listener on an orphaned one. - caps.clear(); -} +export type { StoreRegistryDeps, EventuallyConfig } from "./shared-wallet/bootstrap"; +export { + configure, + getConfig, + resetConfig, + configureStoreRegistry, + getStoreRegistryDeps, + resetStoreRegistry, + setCurrentUser, + getCurrentUser, + getCaps, + capFor, + resetCaps, +} from "./shared-wallet/bootstrap"; // Cap surface — polyfill-era (caps are emulated now; native at migration). // Re-exported here so the whole polyfill API lives under /polyfill. `shareCap` diff --git a/packages/client/src/shared-wallet/access-log.ts b/packages/client/src/shared-wallet/access-log.ts index edccd45..48a9cf2 100644 --- a/packages/client/src/shared-wallet/access-log.ts +++ b/packages/client/src/shared-wallet/access-log.ts @@ -19,7 +19,7 @@ * migration where the broker/verifier enforces isolation natively. */ -import { getCurrentUser } from "../polyfill"; +import { getCurrentUser } from "./bootstrap"; /** Access kind: a document READ or a document WRITE. */ export type AccessOp = "READ" | "WRITE"; diff --git a/packages/client/src/shared-wallet/account-registry.ts b/packages/client/src/shared-wallet/account-registry.ts index a2ba031..ad523c0 100644 --- a/packages/client/src/shared-wallet/account-registry.ts +++ b/packages/client/src/shared-wallet/account-registry.ts @@ -63,7 +63,7 @@ import { sparqlUpdate, sparqlQuery } from "../surface/docs"; import { physicalCreate, physicalQuery, physicalUpdate } from "./physical"; -import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../polyfill"; +import { getCaps, getCurrentUser, getStoreRegistryDeps } from "./bootstrap"; import { ensureRepoOpen } from "../emulated-verifier/open-repo"; import { ensurePhysicalRepoOpen, subscribePhysicalDoc } from "./physical"; import { escapeLiteral, escapeIri, assertNuri } from "../surface/sparql"; diff --git a/packages/client/src/shared-wallet/bootstrap.ts b/packages/client/src/shared-wallet/bootstrap.ts new file mode 100644 index 0000000..4114793 --- /dev/null +++ b/packages/client/src/shared-wallet/bootstrap.ts @@ -0,0 +1,228 @@ +/** + * The injection store — where the consumer application plugs the real SDK in, and + * where the emulation keeps the state that only exists because one wallet hosts every + * identity: the injected `ng`/`useShape`, the registry dependencies, WHO is currently + * connected, and the `CapRegistry` singleton keyed by that holder. + * + * **NO COUNTERPART at any layer, by construction.** Upstream nothing is injected: the + * app imports the SDK, and "who am I" is the session — there is no current-user relay + * because a wallet has exactly one user. This module is the shape of that absence, so + * it belongs with the shared-wallet machinery and evaporates whole at migration. + * + * Extracted from `polyfill.ts` on 2026-08-03. Before that, every internal module + * imported the published ENTRY to reach the config, which made the entry a dependency + * of the code it publishes — cycles `polyfill` <-> `connect` and `polyfill` <-> `inbox`. + * The entry now only re-exports; the internals import this module instead. + */ + +import type { NgLike, UseShapeLike, Nuri, PrincipalId, ReadCap } from "../model/types"; +import type { RegistrySession } from "./account-registry"; +import { CapRegistry } from "../emulated-verifier/caps"; +import { setAccessLog } from "./access-log"; +import { inspectOutbox } from "./outbox-log"; +import { startConnect } from "../emulated-verifier/connect"; + +/** + * Consumer-injected dependencies of the storeRegistry (polyfill-era). The + * registry itself is generic (it knows only native scopes); the consumer wires + * up how to reach the shared-wallet session and how to normalize an identity id + * used as the shim key. Removed at migration along with the whole shim. + */ +export interface StoreRegistryDeps { + /** Resolve the current shared-wallet session (id + private-store anchor). */ + getSession: () => Promise; + /** Normalize an identity id for shim keying. Default: trim (identity-ish). */ + normalizeId?: (id: string) => string; + /** + * POINTER micro-guard budget. The account records now live in a subscribable + * doc-shim (`did:ng:o:...`) reached through a well-known write-once POINTER triple + * in the store-root graph. The doc-shim read is barrier-AUTHORITATIVE, so accounts + * need NO retry (this replaces the deleted account-level `provisionRetry`). The + * ONLY residual sync-lag window is the store-root pointer read itself — one + * write-once triple. This bounded guard re-reads JUST that pointer a few times if a + * fresh cold read misses it; it can never provision or fork an account (worst case: + * a couple extra reads before an existing pointer is seen). Enable it where the REAL + * broker is used (app + e2e). Left UNSET (the default) → `attempts: 1` = single + * read, keeping the synchronous unit fakes fast and unchanged. + */ + pointerGuard?: { attempts?: number; baseMs?: number; maxStepMs?: number }; +} + +export interface EventuallyConfig { + /** The REAL `@ng-org/web` `ng` (injected to avoid a hard import / alias loop). */ + ng: NgLike; + /** The REAL `@ng-org/orm` `useShape`. */ + useShape: UseShapeLike; + /** Shared-wallet credentials — polyfill only (one wallet for everyone). */ + sharedWallet?: { name: string; secret: string }; + /** Initial current user; may also be set later via {@link setCurrentUser}. */ + currentUser?: PrincipalId; + /** + * Turn on the OFF-by-default document access log (see {@link ./access-log}): + * every real read/write is printed, prefixed by the active identity, to + * diagnose the shared-wallet isolation leak. Also enablable without a code + * change via the env var `NG_EVENTUALLY_ACCESS_LOG=1`. Default: false. + */ + debugAccessLog?: boolean; + /** REAL `@ng-org/web` `init` (lifecycle) — forwarded by the lib's `init()`. */ + init?: (...args: any[]) => any; + /** REAL `@ng-org/orm` `initNg` (ORM signals) — forwarded by the lib's `initNg()`. */ + initNg?: (...args: any[]) => any; +} + +let cfg: EventuallyConfig | null = null; +let currentUser: PrincipalId | null = null; +/** Required fields of StoreRegistryDeps after defaults are applied. `pointerGuard` + * defaults to `{ attempts: 1 }` (single read) when the consumer leaves it unset. */ +type ResolvedRegistryDeps = Required< + Pick +>; +let registryDeps: ResolvedRegistryDeps | null = null; +/** + * The map key of the current identity — deliberately NOT the raw id. + * + * A virtual user IS a shim account, and the shim keys accounts by the + * consumer-injected `normalizeId` ("@Alice" and "alice" are ONE account, with one + * set of scope documents). This record must key the same way, or a consumer that + * spells its own id differently between two calls gets a SECOND record and stops + * reading its own documents — the caps are filed under one spelling and looked up + * under the other. Falls back to the raw id while the registry deps are not yet + * configured (nothing can be filed before that anyway). + */ +function capsHolder(): PrincipalId | null { + if (currentUser === null) return null; + return registryDeps ? registryDeps.normalizeId(currentUser) : currentUser; +} + +/** + * The emulated cap registry — one record PER identity (per virtual user), + * resolved through {@link capsHolder} on every call. So switching identity + * SWITCHES heldByHolder (nothing to reset, nothing wiped); see `caps.ts`. Empty until + * the first cap is issued, and while it is empty the read filter passes through + * (no regression). + */ +let caps = new CapRegistry(capsHolder); + +export function configure(c: EventuallyConfig): void { + cfg = c; + currentUser = c.currentUser ?? null; + setAccessLog(c.debugAccessLog ?? false); +} + +/** @internal — used by the SDK-shaped wrappers to reach the injected real SDK. */ +export function getConfig(): EventuallyConfig { + if (!cfg) throw new Error("[ng-eventually] configure() must be called before use"); + return cfg; +} + +/** Reset the injected config back to un-configured (mainly for tests, so a + * suite that calls configure() can restore the not-configured guard state). */ +export function resetConfig(): void { + cfg = null; + currentUser = null; +} + +/** + * Wire the storeRegistry's consumer-injected dependencies (session + identity-id + * normalization). Must be called before any storeRegistry.* use. Separate from + * {@link configure} because it's storeRegistry-specific and, like the shim, + * disappears at migration. + */ +export function configureStoreRegistry(deps: StoreRegistryDeps): void { + // Fire the outbox inspection (Volet 3 of the low-level data-path trace) once, + // on the FIRST successful `getSession()` resolution — the most reliable + // "a session is established" signal available: every low-level reader/writer + // (store-registry, open-repo, read-model, subscribe, inbox) reaches its + // session through this SAME injected `getSession`, so wrapping it HERE catches + // the first success from whichever caller happens to run first, instead of + // tying the probe to one particular call site. Only on SUCCESS (an error + // propagates untouched, exactly as before) and only ONCE per + // `configureStoreRegistry()` call (a fresh session config → a fresh check). + let outboxInspected = false; + const getSession = async (): Promise => { + const session = await deps.getSession(); + if (!outboxInspected) { + outboxInspected = true; + inspectOutbox(); + } + return session; + }; + registryDeps = { + getSession, + normalizeId: deps.normalizeId ?? ((id: string) => id.trim()), + // Default: single read (no re-read). Only the real-broker consumers (app + e2e) + // opt into the bounded pointer micro-guard; unit fakes stay synchronous. + pointerGuard: deps.pointerGuard ?? { attempts: 1 }, + }; +} + +/** @internal — used by the storeRegistry to reach its injected dependencies. */ +export function getStoreRegistryDeps(): ResolvedRegistryDeps { + if (!registryDeps) { + throw new Error("[ng-eventually] configureStoreRegistry() must be called before use"); + } + return registryDeps; +} + +/** Reset storeRegistry deps (mainly for tests). */ +export function resetStoreRegistry(): void { + registryDeps = null; +} + +/** + * Set the current identity id — who the SDK is reading/writing as. In the target + * this is the wallet user established at wallet-import time; here the consumer + * relays that id through this call so the read filter and the inbox `from` know + * who is acting. Passing `null` clears it (no identity yet, e.g. during startup). + */ +export function setCurrentUser(id: PrincipalId | null): void { + const changed = currentUser !== id; + currentUser = id; + // Connecting a user is what triggers inbox processing — the library's job, not + // the app's. Fire-and-forget: this setter is synchronous and every consumer calls + // it from synchronous code, so the work announces itself through the cap + // registry's change signal instead of making callers await. See `connect.ts`. + // + // Gated on the registry being configured, and that is not a test convenience: an + // identity set before the session resolves has nothing to restore and no inbox to + // reach, so firing would be I/O that can only fail. The consumer's real sequence + // is `configureStoreRegistry` then `setCurrentUser`; anything else can call + // `connectedUser()` explicitly. + if (changed && id !== null && registryDeps !== null) startConnect(); +} + +export function getCurrentUser(): PrincipalId | null { + return currentUser; +} + +/** The emulated cap registry — what the current identity holds, plus the emulated + * public store. The read filter and the read-model consult it. */ +export function getCaps(): CapRegistry { + return caps; +} + +/** + * Do I hold the cap of `nuri`? — the held-caps lookup, the ONLY way a cap is + * obtained besides being given one. Returns `undefined` when what I hold has none; + * that is the whole answer the model can give (there is no "may P read D?"). + * + * Shorthand for `getCaps().capFor(nuri)`, exposed because it is the surface the + * consumer actually uses. + */ +export function capFor(nuri: Nuri): ReadCap | undefined { + return caps.capFor(nuri); +} + +/** + * Drop EVERY holder's caps (tests / a fresh wallet). This is **not** what an identity + * change does: switching identity switches heldByHolder, it never wipes one — if it + * wiped, durability would be a lie and per-session re-declaration would come back + * under another name. Nothing in the library calls this on `setCurrentUser`. + */ +export function resetCaps(): void { + // Clear IN PLACE rather than rebuilding: whoever subscribed to the registry's + // change signal (`watchShape`) stays subscribed to the live instance instead of + // silently holding a listener on an orphaned one. + caps.clear(); +} + diff --git a/packages/client/src/shared-wallet/physical.ts b/packages/client/src/shared-wallet/physical.ts index 6baa9bc..eec3b1b 100644 --- a/packages/client/src/shared-wallet/physical.ts +++ b/packages/client/src/shared-wallet/physical.ts @@ -38,7 +38,7 @@ * split once each user opens their own wallet. */ -import { getConfig } from "../polyfill"; +import { getConfig } from "./bootstrap"; import { logAccess } from "./access-log"; import { subscribeDocUnguarded } from "../surface/subscribe"; import { openRepoUnguarded } from "../emulated-verifier/open-repo"; diff --git a/packages/client/src/surface/docs.ts b/packages/client/src/surface/docs.ts index 093a3c8..07855f1 100644 --- a/packages/client/src/surface/docs.ts +++ b/packages/client/src/surface/docs.ts @@ -13,7 +13,7 @@ * app's storeRegistry usage), so this is a drop-in for those raw calls. */ -import { getCaps, getConfig } from "../polyfill"; +import { getCaps, getConfig } from "../shared-wallet/bootstrap"; import { logAccess, enabled as accessLogEnabled } from "../shared-wallet/access-log"; import { isNuri } from "../model/nuri"; import { assertMayReach } from "../emulated-verifier/reach"; diff --git a/packages/client/src/surface/inbox.ts b/packages/client/src/surface/inbox.ts index 7886b9b..c0f80e8 100644 --- a/packages/client/src/surface/inbox.ts +++ b/packages/client/src/surface/inbox.ts @@ -29,7 +29,7 @@ import { depositInto, sparqlQuery } from "./docs"; import { subscribeDoc } from "./subscribe"; import { ensureRepoOpen } from "../emulated-verifier/open-repo"; -import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../polyfill"; +import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../shared-wallet/bootstrap"; import { addLink, documentInboxAddress, isOwnInbox } from "../shared-wallet/account-registry"; import { escapeLiteral } from "./sparql"; import { hasReadCap } from "../model/nuri"; diff --git a/packages/client/src/surface/lifecycle.ts b/packages/client/src/surface/lifecycle.ts index b76df4f..8ff9402 100644 --- a/packages/client/src/surface/lifecycle.ts +++ b/packages/client/src/surface/lifecycle.ts @@ -5,7 +5,7 @@ * a hook point later (e.g. opening the shared wallet on `init`). */ -import { getConfig } from "../polyfill"; +import { getConfig } from "../shared-wallet/bootstrap"; /** Forwards to the real `@ng-org/web` `init`. */ export function init(...args: any[]): any { diff --git a/packages/client/src/surface/ng-proxy.ts b/packages/client/src/surface/ng-proxy.ts index 822e6c0..1291412 100644 --- a/packages/client/src/surface/ng-proxy.ts +++ b/packages/client/src/surface/ng-proxy.ts @@ -4,7 +4,7 @@ * surface stays identical to `@ng-org/web`'s `ng`. */ -import { getConfig, getCaps, getCurrentUser } from "../polyfill"; +import { getConfig, getCaps, getCurrentUser } from "../shared-wallet/bootstrap"; import type { Nuri } from "../model/types"; export function makeNg(): Record { diff --git a/packages/client/src/surface/read-model.ts b/packages/client/src/surface/read-model.ts index 22b2173..ad6faa8 100644 --- a/packages/client/src/surface/read-model.ts +++ b/packages/client/src/surface/read-model.ts @@ -42,7 +42,7 @@ */ import { docCreate, sparqlUpdate, sparqlQuery } from "./docs"; -import { getCaps, getStoreRegistryDeps } from "../polyfill"; +import { getCaps, getStoreRegistryDeps } from "../shared-wallet/bootstrap"; import { mustNotAttempt } from "../emulated-verifier/reach"; import { ensureReposOpen } from "../emulated-verifier/open-repo"; import { assertNuri } from "./sparql"; diff --git a/packages/client/src/surface/subscribe.ts b/packages/client/src/surface/subscribe.ts index 26b2fb0..1e8be76 100644 --- a/packages/client/src/surface/subscribe.ts +++ b/packages/client/src/surface/subscribe.ts @@ -33,7 +33,7 @@ * builds a set of these with per-doc error isolation to preserve that property. */ -import { getConfig, getStoreRegistryDeps } from "../polyfill"; +import { getConfig, getStoreRegistryDeps } from "../shared-wallet/bootstrap"; import { assertMayReach } from "../emulated-verifier/reach"; import type { Nuri } from "../model/types"; diff --git a/packages/client/src/surface/use-shape.ts b/packages/client/src/surface/use-shape.ts index a82de6d..635e53c 100644 --- a/packages/client/src/surface/use-shape.ts +++ b/packages/client/src/surface/use-shape.ts @@ -6,7 +6,7 @@ * only delivers documents whose cap the wallet holds. */ -import { getConfig, getCaps } from "../polyfill"; +import { getConfig, getCaps } from "../shared-wallet/bootstrap"; import { makeReadFilteredView } from "../emulated-verifier/read-filter"; export function useShape(shapeType: unknown, scope: unknown): unknown { diff --git a/packages/client/src/surface/watch-shape.ts b/packages/client/src/surface/watch-shape.ts index 73fe26d..de2d172 100644 --- a/packages/client/src/surface/watch-shape.ts +++ b/packages/client/src/surface/watch-shape.ts @@ -51,7 +51,7 @@ * `isError` fires ONLY on a real thrown exception in the pipeline. */ -import { getCaps, getCurrentUser } from "../polyfill"; +import { getCaps, getCurrentUser } from "../shared-wallet/bootstrap"; import { ensureReposOpen, getSyncState } from "../emulated-verifier/open-repo"; import { readUnion, type UnionSubject } from "./read-model"; import { subscribeDoc, type Unsubscribe } from "./subscribe";