/*! * Copyright (c) 2026 Interop Alliance. All rights reserved. */ /** * The Login-With-Wallet orchestration: one-popup App Connect. * * A single CHAPI `get` carries the {@link buildAppConnectVpr} request. The * wallet -- in the same round -- matches an existing app key or mints a fresh * one (the first-run branch is wallet-internal now), then returns the app-key * credential and the delegated zcaps embedded in one signed response VP. So * there is no second store popup and no separate grants popup: * * - Returning: the wallet returns the credential; we recover the seed and * verify its self-issue/origin/DID binding. * - First run: the wallet mints the seed, self-issues the same-shaped * credential, and marks `presentation.appConnect.firstRun`. * * A wallet that predates `AppConnectQuery` cannot satisfy it and returns no * app-key credential; that surfaces as {@link WalletUnsupportedError} (fail * closed, legibly), distinct from a user cancel (a null CHAPI response). * * Hot restore (seed + grants already persisted locally) never reaches this * module -- the caller's session restore short-circuits it. */ import type { IZcap } from '@interop/data-integrity-core'; import type { DocumentLoader } from '../identity/documentLoader.js'; import type { IdentityAgents } from '../identity/agents.js'; import { type GrantRequestCollection } from './loginRequest.js'; import { type CheckedGrants } from './verifyResponse.js'; import type { ParsedGrants } from '../grants.js'; /** * The cohesive configuration for a Login-With-Wallet flow. App-specific values * are injected here rather than baked in; this becomes part of the library's * central app config later. */ export interface LoginConfig { /** * This app's own web origin (the anti-phishing bind on the app key). */ appOrigin: string; /** * Human-readable app name, used in the wallet consent reason lines. */ appName: string; /** * This app's canonical URL: the application's identity among the * applications on its origin. It must be an absolute URL, carry no fragment, * and be same-origin with `appOrigin`; the flow serializes it once and uses * that serialization for the request, the credential lookup, and the parse * check alike. */ appUrl: string; /** * The collections to request read/write grants for (WAS collection id + * visibility; `'public'` selects the `https://w3id.org/byoe#public-collection` descriptor). */ collections: GrantRequestCollection[]; /** * WAS collection ids of wallet-owned collections to request read-and-decrypt * access to (the `https://w3id.org/byoe#shared-wallet-collection` grant). * Read-only; never replicated. */ sharedCollections?: string[]; /** * The JSON-LD document loader (see `createDocumentLoader`). */ documentLoader: DocumentLoader; /** * The CHAPI mediator base URL (defaults to `DEFAULT_MEDIATOR_BASE`). */ mediatorBase?: string; } /** * A user-facing progress phase, for the login page's status line. The one-popup * App Connect flow has just two: `connecting` (building the request and awaiting * the wallet) and `verifying` (checking the wallet's response). */ export type LoginPhase = 'connecting' | 'verifying'; export interface LoginOutcome { seed: Uint8Array; identity: IdentityAgents; grants: IZcap[]; parsed: ParsedGrants; /** * ISO timestamp: the earliest expiry across the grants. */ expires: string; /** * Whether this login created a brand-new app key (first run). */ firstRun: boolean; } /** * Thrown when the user cancels/dismisses a wallet popup. */ export declare class LoginCancelledError extends Error { constructor(step: string); } /** * Thrown when the wallet answered but returned no app-key credential -- the * fail-closed signal that the wallet predates `AppConnectQuery` (it rendered the * query unsatisfiable). Distinct from a user cancel so the UI can prompt an * update instead of showing a generic verification error. */ export declare class WalletUnsupportedError extends Error { constructor(); } /** * Re-requests storage grants for `identity` over a fresh App Connect popup and * validates them. The expired-access reconnect path: the seed already exists, so * only the grants need renewing. The wallet matches the same app key and * re-delegates; the returned credential/`appConnect` marker are ignored here. * * @param options {object} * @param options.identity {IdentityAgents} * @param options.config {LoginConfig} * @param [options.onPhase] {Function} * @returns {Promise} */ export declare function requestGrants({ identity, config, onPhase }: { identity: IdentityAgents; config: LoginConfig; onPhase?: (phase: LoginPhase) => void; }): Promise; /** * Runs the one-popup Login-With-Wallet (App Connect) flow. A single CHAPI `get` * returns the app-key credential (matched or minted wallet-side) plus the * delegated grants in one signed VP. Throws `LoginCancelledError` on a user * cancel (a null CHAPI response), `WalletUnsupportedError` when the wallet * answered but returned no app key (an old wallet that could not satisfy * `AppConnectQuery`), and `Error` on any verification failure. Nothing is * persisted here (the caller persists). * * @param options {object} * @param options.config {LoginConfig} * @param [options.onPhase] {Function} * @returns {Promise} */ export declare function loginWithWallet({ config, onPhase }: { config: LoginConfig; onPhase?: (phase: LoginPhase) => void; }): Promise; //# sourceMappingURL=loginFlow.d.ts.map