/**
 * `session` — a person's **sign-in session** (wire token class
 * `control_plane_session`). One session, bound to the principal, graded by how
 * it was minted (`grade` on every mint response and on `GET /agent/v1/whoami`):
 *
 * - `browser` — the console: email magic link, passkey, Google, or GitHub.
 * - `loopback` — `run402 login`: the loopback-PKCE browser ceremony
 *   ({@link Session.buildCliAuthorizeUrl} + {@link Session.exchangeCliToken}).
 *   Full and step-up-able.
 * - `device` — `run402 login --device`: RFC 8628 device authorization
 *   ({@link Session.deviceStart} + {@link Session.devicePoll}). Read-only: the
 *   gateway refuses every mutation with `403 SESSION_READ_ONLY`.
 *
 * Reached as `r.session.*`. Isomorphic — no Node APIs; the loopback server and
 * PKCE generation live in the Node CLI. The public *mint* methods send no auth
 * (the body, the magic-link token, or the code + verifier is the credential);
 * the *session-bound* methods take `opts.token` to send the bearer explicitly,
 * and fall back to the credential provider's default auth (e.g.
 * {@link controlPlaneSessionCredentials} or a SIWX wallet) when omitted.
 *
 * WebAuthn option/assertion payloads are opaque passthroughs (`unknown`) — the
 * browser runs the actual ceremony; a headless client cannot.
 *
 * High-stakes writes (invite, membership, transfer, delete) require a **fresh
 * passkey** — a magic-link/OAuth session does NOT satisfy step-up, so the
 * gateway returns {@link StepUpRequiredError}; `stepUpOptions`/`stepUpVerify`
 * are how a long-lived session re-establishes that freshness. A write approval
 * ({@link WriteApproval}) never satisfies step-up.
 */
import type { Client } from "../kernel.js";
import type { SessionGrade, WhoAmIResult } from "./org.types.js";
/**
 * A minted sign-in session (`POST /agent/v1/control-plane/cli/token`,
 * `…/cli/device/token`, and the browser mint routes). Forward-compatible.
 */
export interface ControlPlaneSession {
    control_plane_session_token: string;
    token_type?: string;
    /** Relative lifetime in seconds. */
    expires_in?: number;
    /** How it was minted: `browser`, `loopback`, or `device` (read-only). */
    grade?: SessionGrade | (string & {});
    /** The principal id. */
    principal_id?: string;
    /** Auth methods satisfied (e.g. `["passkey"]`). */
    amr?: string[];
    /** ISO-8601 absolute expiry, when the mint route reports one. */
    absolute_expires_at?: string;
    [key: string]: unknown;
}
/** RFC 8628 device-authorization start response (`POST …/cli/device`). */
export interface DeviceAuthStart {
    device_code: string;
    user_code: string;
    verification_uri: string;
    /** Pre-fills the user_code so the person can click straight through. */
    verification_uri_complete?: string;
    expires_in: number;
    /** Minimum seconds between `devicePoll` calls. */
    interval: number;
}
/**
 * Result of one {@link Session.devicePoll}. The non-approved states are the
 * RFC 8628 token error codes — expected polling states, NOT thrown errors, so
 * callers can run the poll loop without try/catch. An approved session carries
 * `grade: "device"`.
 */
export type DevicePollResult = {
    kind: "approved";
    session: ControlPlaneSession;
} | {
    kind: "authorization_pending";
} | {
    kind: "slow_down";
} | {
    kind: "access_denied";
} | {
    kind: "expired_token";
};
/** Parameters for {@link Session.buildCliAuthorizeUrl}. */
export interface CliAuthorizeParams {
    /** The CLI's loopback redirect, e.g. `http://127.0.0.1:54321/callback`. */
    redirectUri: string;
    /** PKCE S256 challenge = base64url(sha256(verifier)). */
    codeChallenge: string;
    /** Opaque CSRF state echoed back on the redirect. */
    state: string;
    /** Replay nonce. */
    nonce: string;
}
/** Parameters for {@link Session.exchangeCliToken}. */
export interface CliTokenExchange {
    /** Authorization code received on the loopback redirect. */
    code: string;
    /** The PKCE verifier whose hash was sent as `codeChallenge`. */
    codeVerifier: string;
    /** Must match the `redirectUri` used at authorize time. */
    redirectUri: string;
    /** Must match the `state` used at authorize time. */
    state: string;
}
/** OAuth identity providers bridged for sign-in. */
export type ControlPlaneOAuthProvider = "google" | "github";
/** Generic, non-enumerating response from {@link Session.email}. */
export interface MagicLinkSendResult {
    status: string;
    message: string;
    [key: string]: unknown;
}
/**
 * Result of {@link Session.consumeRecoveryCode} — a minted session that
 * cannot perform high-stakes ops until a passkey is enrolled
 * (`must_enroll_passkey: true`). Recovery `amr` never satisfies step-up.
 */
export interface RecoveryConsumeResult extends ControlPlaneSession {
    must_enroll_passkey?: boolean;
    note?: string;
}
/** Result of {@link Session.refresh} (`POST …/session/refresh`). */
export interface ControlPlaneRefreshResult {
    control_plane_session_token: string;
    token_type?: string;
    expires_in?: number;
    [key: string]: unknown;
}
/** WebAuthn options envelope (`{ options }`) — opaque; handed to the browser. */
export interface WebAuthnOptionsResult {
    options: unknown;
    [key: string]: unknown;
}
/** Result of {@link Session.enrollPasskeyVerify}. */
export interface EnrollPasskeyResult {
    status: string;
    credential_id: string;
    [key: string]: unknown;
}
/** Result of {@link Session.stepUpVerify}. */
export interface StepUpVerifyResult {
    status: string;
    stepped_up: boolean;
    [key: string]: unknown;
}
/** Result of {@link Session.issueRecoveryCodes} — shown ONCE. */
export interface RecoveryCodesResult {
    status: string;
    recovery_codes: string[];
    note?: string;
    [key: string]: unknown;
}
/** One active authenticator (no secret material). Forward-compatible. */
export interface Authenticator {
    id: string;
    kind: string;
    /** Provider-side subject hint (e.g. masked email / credential label); absent when unset. */
    subject_hint?: string;
    /** ISO-8601 enrollment time. */
    added_at?: string;
    /** ISO-8601 last-use time; absent when never used. */
    last_used_at?: string;
    [key: string]: unknown;
}
/** Result of {@link Session.revokeAuthenticator}. */
export interface AuthenticatorRevokeResult {
    status: string;
    kind: string;
    [key: string]: unknown;
}
/** Options bag carrying the optional `control_plane_session` bearer. */
export interface SessionTokenOpts {
    /**
     * The `control_plane_session` bearer. When omitted, the request falls back to
     * the credential provider's default auth (e.g. {@link controlPlaneSessionCredentials}).
     */
    token?: string;
}
export declare class Session {
    private readonly client;
    constructor(client: Client);
    /**
     * Build the loopback-PKCE authorize URL `run402 login` opens in the browser
     * (`GET /agent/v1/control-plane/cli/authorize`). Pure — no network. The
     * caller generates `codeChallenge`/`state`/`nonce` and runs the redirect
     * server on `127.0.0.1`.
     */
    buildCliAuthorizeUrl(params: CliAuthorizeParams): string;
    /**
     * Exchange the loopback authorization code (+ PKCE verifier) for a
     * `loopback`-grade sign-in session (`POST …/cli/token`). Unauthenticated —
     * the code + verifier are the credential.
     */
    exchangeCliToken(params: CliTokenExchange): Promise<ControlPlaneSession>;
    /**
     * Begin RFC 8628 device authorization (`POST …/cli/device`) for
     * `run402 login --device`. Unauthenticated. Returns the codes the CLI prints
     * (`user_code` + `verification_uri`) plus the poll `interval` and
     * `expires_in`. The person approves in the console, which needs a recent
     * sign-in (`403 RECENT_SIGN_IN_REQUIRED` otherwise).
     */
    deviceStart(): Promise<DeviceAuthStart>;
    /**
     * Poll once for approval (`POST …/cli/device/token`). Bypasses the kernel's
     * error mapping on purpose: the RFC 8628 error codes (`authorization_pending`,
     * `slow_down`, ...) are normal polling states returned as data, not
     * exceptions. Only an unexpected response shape throws. The approved session
     * is `device` grade (read-only).
     */
    devicePoll(deviceCode: string): Promise<DevicePollResult>;
    /**
     * Send a control-plane sign-in magic link to `email`
     * (`POST /agent/v1/control-plane/session/email`). Non-enumerating: an
     * identical response whether or not the email can sign in. Rate-limited.
     */
    email(input: {
        email: string;
    }): Promise<MagicLinkSendResult>;
    /**
     * Exchange a magic-link token for a sign-in session
     * (`POST …/session/email/verify`). Verifies the email, resolves/creates the
     * principal, **auto-claims any pending invites**, and mints the session
     * (`amr: ["email"]`).
     */
    verifyEmail(input: {
        token: string;
    }): Promise<ControlPlaneSession>;
    /**
     * Get WebAuthn login options for an email's passkeys
     * (`POST …/session/passkey/options`). Opaque — pass `options` to the browser's
     * `navigator.credentials.get`.
     */
    passkeyOptions(input: {
        email: string;
    }): Promise<WebAuthnOptionsResult>;
    /**
     * Verify a WebAuthn assertion and mint a session (`amr: ["passkey"]`)
     * (`POST …/session/passkey/verify`). `response` is the opaque assertion from
     * the browser.
     */
    passkeyVerify(input: {
        email: string;
        response: unknown;
    }): Promise<ControlPlaneSession>;
    /**
     * Build the browser OAuth start URL for `provider`
     * (`GET …/oauth/:provider/start`). Pure — no network. Open it in a browser;
     * the gateway 302s to the provider, then the callback lands on the console
     * with the session token in the URL fragment.
     *
     * Note: the live bridge can return `503` until the gateway provisions the
     * provider's `CONTROL_PLANE_{GOOGLE,GITHUB}_*` client credentials.
     */
    oauthUrl(provider: ControlPlaneOAuthProvider): string;
    /**
     * Run the recovery-code ceremony (`POST …/recovery/consume`). Mints a session
     * with `amr: ["recovery_code"]` which **cannot** do high-stakes ops
     * (`must_enroll_passkey: true`) — enrol a passkey to restore full access.
     */
    consumeRecoveryCode(input: {
        code: string;
    }): Promise<RecoveryConsumeResult>;
    /**
     * Resolve the session's principal, memberships, and `session` —
     * `{ grade, amr, amr_times }` (`GET /agent/v1/whoami`). The `memberships`
     * reflect any invites auto-claimed at sign-in. With no `token` the request
     * uses the credential provider, and `session` is `null` for a wallet caller.
     */
    whoami(opts?: SessionTokenOpts): Promise<WhoAmIResult>;
    /** Rotate the access token (`POST …/session/refresh`). */
    refresh(opts?: SessionTokenOpts): Promise<ControlPlaneRefreshResult>;
    /** Sign out — revoke the session server-side (`POST …/session/revoke`). Idempotent. */
    revoke(opts?: SessionTokenOpts): Promise<{
        status: string;
        [key: string]: unknown;
    }>;
    /** WebAuthn registration options for a new passkey (`POST …/passkey/enroll/options`). */
    enrollPasskeyOptions(opts?: SessionTokenOpts): Promise<WebAuthnOptionsResult>;
    /** Verify a passkey registration (`POST …/passkey/enroll/verify`). `label` names the authenticator. */
    enrollPasskeyVerify(input: {
        response: unknown;
        label?: string | null;
    } & SessionTokenOpts): Promise<EnrollPasskeyResult>;
    /**
     * WebAuthn step-up options for a high-stakes op (`POST …/step-up/options`).
     * `opClass` binds the elevation, e.g. `"org.invite"` / `"org.membership"` /
     * `"project.transfer"` (see {@link StepUpRequiredError.requiredAmr}).
     */
    stepUpOptions(input?: {
        opClass?: string;
    } & SessionTokenOpts): Promise<WebAuthnOptionsResult>;
    /**
     * Verify a step-up assertion (`POST …/step-up/verify`) → refreshes session
     * passkey-freshness and records an action-bound elevation when `opClass` (and
     * optionally `objectKind`/`objectId`) are given. Retry the gated write after.
     */
    stepUpVerify(input: {
        response: unknown;
        opClass?: string;
        objectKind?: string | null;
        objectId?: string | null;
    } & SessionTokenOpts): Promise<StepUpVerifyResult>;
    /** (Re)issue recovery codes — shown ONCE (`POST …/recovery/issue`). */
    issueRecoveryCodes(opts?: SessionTokenOpts): Promise<RecoveryCodesResult>;
    /** List my active authenticators — no secret material (`GET …/authenticators`). */
    listAuthenticators(opts?: SessionTokenOpts): Promise<Authenticator[]>;
    /**
     * Revoke an authenticator (`DELETE …/authenticators/:id`). Step-up enforced;
     * the gateway refuses to remove the last passkey of a sole org owner
     * (`OWNER_NEEDS_PASSKEY`).
     */
    revokeAuthenticator(input: {
        id: string;
    } & SessionTokenOpts): Promise<AuthenticatorRevokeResult>;
    /**
     * My own source-access key + wrapper set, ciphertext included
     * (`GET /agent/v1/source-access/wrappers`) — the states/scheme read behind
     * `run402 repos access`. Principal-scoped structurally: only the
     * caller's own wrappers ever come back. Enrollment/activation/revocation
     * are console ceremonies (WebAuthn); this SDK surface is read-only.
     */
    sourceAccessWrappers(opts?: SessionTokenOpts): Promise<SourceAccessWrappersResult>;
    /**
     * Export my versioned member recovery bundle
     * (`GET /agent/v1/source-access/recovery-bundle`, format
     * `r402s-member-recovery-bundle/v1`) — key identity + every ACTIVE wrapper
     * ciphertext. A server-side wrapper row alone is NOT offline backup; this
     * bundle kept in the member's own storage (separately from the source
     * recovery code) is what `r402s-recover` opens with no run402 server. The
     * gateway stamps the export as recovery-posture evidence.
     */
    sourceAccessRecoveryBundle(opts?: SessionTokenOpts): Promise<SourceAccessRecoveryBundleResult>;
}
/** One wrapper row as `GET /agent/v1/source-access/wrappers` returns it. */
export interface SourceAccessWrapper {
    wrapper_id: string;
    encryption_key_id: string;
    kind: "webauthn_prf" | "recovery_code";
    state: "pending" | "active" | "revoked";
    format_version: string;
    credential_subject: string | null;
    wrapper_ciphertext: string;
    blob_sha256: string;
    created_at: string;
    activated_at: string | null;
}
export interface SourceAccessWrappersResult {
    principal_id: string;
    /** Null when the principal has never enrolled a source-access key. */
    encryption_key: {
        encryption_key_id: string;
        ek_fingerprint: string;
        public_key: string;
        suite: string;
        custody_scheme: string;
        state: string;
        created_at: string;
    } | null;
    wrappers: SourceAccessWrapper[];
}
/** `r402s-member-recovery-bundle/v1` exactly as the gateway returns it (see the node-side `VaultMemberRecoveryBundle` for the recover-input twin). */
export interface SourceAccessRecoveryBundleResult {
    format: "r402s-member-recovery-bundle/v1";
    exported_at: string;
    principal_id: string;
    encryption_key_id: string;
    ek_fingerprint: string;
    public_key: string;
    suite: string;
    custody_scheme: string;
    wrappers: Array<Omit<SourceAccessWrapper, "encryption_key_id" | "state" | "activated_at">>;
    note: string;
}
//# sourceMappingURL=session.d.ts.map