import { O as OAuthFlowLogger, U as UserAuthConfig, A as AuthConfigStorage, C as CredentialStore, F as FileFormat } from './file-format-Bpmgm2Po.mjs'; export { a as ConfigStorage, D as DeactivateDirectoryResult, b as DirectoryBindingOperations, c as DirectoryBindingsStorage, L as LoginOrRefreshFailureReason, d as LoginOrRefreshResult, e as LoginProps, f as OAuthFlowContext, P as ProfileConfigOperations, g as ProfileStore, T as TemporaryPreviewAccount, h as createOAuthFlow, i as createProfileStore, j as generateAuthUrl, k as generateRandomState, v as validateProfileName } from './file-format-Bpmgm2Po.mjs'; import { ApiCredentials } from '@cloudflare/workers-utils'; import { SpawnSyncReturns } from 'node:child_process'; /** `CLOUDFLARE_API_TOKEN` (legacy alias `CF_API_TOKEN`): a scoped API token. */ declare const getCloudflareAPITokenFromEnv: () => string | undefined; /** `CLOUDFLARE_API_KEY` (legacy alias `CF_API_KEY`): the global API key. */ declare const getCloudflareGlobalAuthKeyFromEnv: () => string | undefined; /** `CLOUDFLARE_EMAIL` (legacy alias `CF_EMAIL`): the account email, paired with * the global API key. */ declare const getCloudflareGlobalAuthEmailFromEnv: () => string | undefined; interface GetAuthFromEnvOptions { /** * Whether to honour the global API key + email pair * (`CLOUDFLARE_API_KEY` + `CLOUDFLARE_EMAIL`, surfaced as * `X-Auth-Key`/`X-Auth-Email`). Defaults to `true` (Wrangler's behaviour). * CLIs that only support scoped API tokens / OAuth should pass `false`. */ allowGlobalAuthKey?: boolean; } /** * Resolve Cloudflare API credentials from environment variables. * * Priority (highest to lowest), matching Wrangler's historical order: * 1. Global API key + email (`CLOUDFLARE_API_KEY` + `CLOUDFLARE_EMAIL`) — * only when `allowGlobalAuthKey` is `true`. * 2. API token (`CLOUDFLARE_API_TOKEN`). * * @returns the resolved credentials, or `undefined` when no env credentials * are present. */ declare function getAuthFromEnv(options?: GetAuthFromEnvOptions): ApiCredentials | undefined; /** * Clear internal caches. Exported for use in tests only. */ declare function clearAccessCaches(): void; /** * Probe a domain to detect whether it is sitting behind Cloudflare Access. * * A 302 to `cloudflareaccess.com` is the canonical signal. Service-auth-only * Access applications return a hard 403 instead and are therefore not detected * here — see {@link getAccessHeaders} for how this is handled. */ declare function domainUsesAccess(domain: string, logger: OAuthFlowLogger): Promise; /** * Get the headers needed to authenticate with an Access-protected domain. * * @param domain The hostname of the Access-protected domain (e.g. `"example.com"`). * @param options logger + an `isNonInteractiveOrCI` predicate used to * produce an actionable error in CI; both default to no-op / `false`. * @returns * - Service token headers (`CF-Access-Client-Id` + `CF-Access-Client-Secret`) if env vars are set * - A `Cookie: CF_Authorization=...` header if obtained via `cloudflared` (interactive only) * - An empty object if the domain is not behind Access * @throws {UserError} If the response does not contain a `CF_Authorization` cookie, * indicating the service token is invalid, expired, or lacks a Service Auth policy. * Also throws in non-interactive environments when the domain is behind Access * but no service token credentials are configured. */ declare function getAccessHeaders(domain: string, options: { logger: OAuthFlowLogger; isNonInteractiveOrCI?: () => boolean; /** Aborts a pending `cloudflared` authorization and kills its process. */ signal?: AbortSignal; }): Promise>; /** * `WRANGLER_AUTH_URL` is the path that is used to access OAuth * for the Cloudflare APIs. * * Normally you should not need to set this explicitly. * If you want to switch to the staging environment set the * `WRANGLER_API_ENVIRONMENT=staging` environment variable instead. */ declare const getAuthUrlFromEnv: () => string; /** * `CLOUDFLARE_ACCOUNT_ID` overrides the account inferred from the current user. * * This is a Cloudflare-wide variable (not wrangler-specific), so it lives in the * shared core rather than a consumer layer. `CF_ACCOUNT_ID` is the deprecated * spelling. * * Every caller feeds the result into a Cloudflare API URL path, so the value is * validated here rather than at each call site. An empty string is treated as * unset so callers keep falling back to the cached / interactively selected * account. */ declare function getCloudflareAccountIdFromEnv(): string | undefined; /** * `CLOUDFLARE_AUTH_USE_KEYRING` overrides where OAuth credentials are stored. * * - `true` — force-store credentials in the OS keychain. If the keychain * cannot be reached, the resolver throws rather than silently * falling back, so security-sensitive callers know their * explicit opt-in did not take effect. * - `false` — force-store credentials in the plaintext TOML file, * even if the consumer's persistent `keyring_enabled` preference * is set. * - unset — fall back to the consumer's persistent preference (e.g. the * one written by `wrangler login --use-keyring`). */ declare const getCloudflareAuthUseKeyringFromEnv: () => boolean | undefined; /** * Build the URL the user should visit to approve a device authorization * request, with the `user_code` embedded as a query parameter so the user * does not have to type it manually. * * Per RFC 8628 §3.3.1, this is the "verification_uri_complete" optimization * for non-textual transmission (such as QR codes). Authorization servers may * return their own `verification_uri_complete` in the device authorization * response — prefer that when it is provided. Use this helper as a fallback * when only `verification_uri` is available. * * Extracted into its own module (mirroring `generate-auth-url.ts`) so that * tests can mock the generated URL deterministically. */ declare const generateVerificationUrl: ({ verificationUri, userCode, }: { verificationUri: string; userCode: string; }) => string; declare const TEMPORARY_TERMS_PROMPT: string; declare const TEMPORARY_TERMS_NOTICE: string; /** * Character set to generate code verifier defined in rfc7636. */ declare const PKCE_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; interface RefreshToken { value: string; } interface AccessToken { value: string; expiry: string; } /** * The auth state that is stored on disk in the user auth config file (TOML). * Read on demand by {@link readStoredAuthState} — never cached at module scope * so that environment variables loaded after import (e.g. from `.env`) take * priority correctly. */ interface StoredAuthState { accessToken?: AccessToken; refreshToken?: RefreshToken; scopes?: string[]; /** @deprecated - this field was only provided by the deprecated v1 `wrangler config` command. */ deprecatedApiToken?: string; } /** * Read the on-disk auth state. Called on demand from every site that needs the * stored OAuth tokens or the deprecated v1 `api_token`, rather than being * cached at module scope, so that environment-based credentials loaded after * module import are honoured by the rest of wrangler. * * @return an empty object when no auth config file exists or the file cannot * be parsed — the caller treats this as "not logged in via local OAuth". * * @param options.configOverride seed the state from an in-memory config (used by * the OAuth login flow before it writes to disk). * @param options.warningLogger if provided, a one-time warning is emitted when a * deprecated v1 `api_token` is found on disk. Pass the consumer's logger (e.g. * wrangler's logger singleton) to surface this to the user. * @param options.storage the persistence backend to read from, injected by the * consumer (e.g. wrangler's TOML-file-on-disk storage under the global Wrangler * config directory). */ declare function readStoredAuthState(options: { configOverride?: UserAuthConfig; warningLogger?: Pick; storage: AuthConfigStorage; }): StoredAuthState; /** * Absolute path to the plaintext TOML credentials file for the given auth * profile (defaulting to the active Cloudflare API environment's default * profile). * * `configPath` is the consumer's global config directory — the client (e.g. * wrangler, or a future `cf` CLI) owns where its config lives, so it is passed * in rather than resolved here. The environment is appended to the * default-profile filename so callers running with * `WRANGLER_API_ENVIRONMENT=staging` get a separate file from production; named * profiles get `.toml`. The path stays exposed so the migration code, * defensive scrubs on logout, and tests that assert against it can all point at * the same location as the {@link FileCredentialStore}. */ declare function getAuthConfigFilePath(configPath: string, profile?: string, extension?: string): string; /** * The plaintext-TOML credentials store. * * Used as the default backend when the user hasn't opted into keyring * storage, and as the soft-fallback when keyring storage is requested * but a backend isn't available. */ declare class FileCredentialStore implements CredentialStore { private readonly configPath; private readonly profile?; private readonly format; readonly kind: "file"; /** * @param configPath consumer-provided global config directory (the CLI * owns where its config lives, so workers-auth never resolves it itself). * @param profile the auth profile (defaults to the active environment's * default profile). * @param format on-disk file format (defaults to TOML for wrangler's * historical layout; cf and other CLIs pass JSON). */ constructor(configPath: string, profile?: string | undefined, format?: FileFormat); private filePath; read(): UserAuthConfig | undefined; write(config: UserAuthConfig): void; clear(): boolean; path(): string; describe(): string; } /** * A small abstraction over OS keyring backends, scoped to "store/retrieve * an arbitrary fixed-size key" rather than "store a credential blob". * * Keeping the responsibility this narrow means: * - The 2.5 KB macOS Keychain item limit (and similar limits elsewhere) * is never hit — we only ever store ~44 bytes of base64. * - Per-platform code stays trivial; richer credential shapes can grow * freely inside the encrypted file without touching the keyring. * - The same `KeyProvider` is reusable for non-OAuth secrets in the * future (e.g. account-scoped API tokens). * * Implementations are instantiated with the consumer's `serviceName` * (e.g. "wrangler") so the same library can serve multiple Cloudflare * CLIs without collisions. */ interface KeyProvider { /** * Return the previously-stored key, or `undefined` when nothing has * been stored for this `(serviceName, accountName)` pair. Backend * failures throw so callers can surface meaningful errors. */ getKey(): Uint8Array | undefined; /** Persist the given key, overwriting any previous value. */ setKey(key: Uint8Array): void; /** Remove the stored key. Idempotent — no-op when nothing is stored. */ deleteKey(): void; /** * Human-readable description of where the key is stored, surfaced via * the {@link CredentialStore.describe} chain. */ describe(): string; } /** * Absolute path to the encrypted credentials file for the given auth profile * (defaulting to the active Cloudflare API environment's default profile). * * `configPath` is the consumer's global config directory (see * {@link getAuthConfigFilePath}). Sibling of the plaintext `.toml` so * the migration code can non-destructively read the old file before writing the * new one. */ declare function getEncryptedAuthConfigFilePath(configPath: string, profile?: string): string; /** * Result of a successful migration from a plaintext TOML file * into an encrypted file backed by a `KeyProvider`. Surfaced so the * resolver can log a one-line summary when migration runs. */ interface PlaintextMigrationResult { plaintextPath: string; encryptedPath: string; keyProviderDescription: string; } /** * Optional callback invoked by {@link EncryptedFileCredentialStore.read} * when it transparently migrates a plaintext TOML file into the * encrypted file on first read. * * The resolver wires this to its logger; left undefined when the store * is constructed standalone (e.g. by tests). */ type OnPlaintextMigration = (result: PlaintextMigrationResult) => void; /** * Credentials store backed by an AES-256-GCM-encrypted file on disk and a * 32-byte encryption key held in the OS keyring via a {@link KeyProvider}. * * The combination decouples credential payload size from any per-platform * keyring item size limit (notably the ~2.5 KB macOS Keychain limit on * generic-password items): the keyring entry is always small (~44 bytes * of base64), while the credential blob lives in the encrypted file and * is free to grow as the schema evolves. * * Threat model: * - File leaked from a backup without the keyring entry: ciphertext is * useless, GCM auth tag prevents tampering. * - Keyring entry leaked without the file: a bare 32-byte key, useless * without the ciphertext. * - Attacker with full local user access: can decrypt (same as * direct-keyring storage — both backends expose secrets to root / * same-user processes). */ declare class EncryptedFileCredentialStore implements CredentialStore { private readonly configPath; private readonly keyProvider; private readonly onPlaintextMigration?; private readonly profile?; private readonly format; readonly kind: "encrypted-file"; /** * @param configPath consumer-provided global config directory (the CLI * owns where its config lives, so workers-auth never resolves it itself). * @param keyProvider the OS-keyring backend holding the encryption key. * @param onPlaintextMigration optional callback invoked when a plaintext * file is migrated into the encrypted layout on first read. * @param profile the auth profile (defaults to the active environment's * default profile). * @param format on-disk format of the plaintext sibling file and the * encrypted payload (defaults to TOML for wrangler). */ constructor(configPath: string, keyProvider: KeyProvider, onPlaintextMigration?: OnPlaintextMigration | undefined, profile?: string | undefined, format?: FileFormat); private plaintextPath; read(): UserAuthConfig | undefined; write(config: UserAuthConfig): void; clear(): boolean; path(): string; describe(): string; private readEncryptedFile; private migrateFromPlaintext; /** * Return the existing encryption key, or generate + persist a fresh * one when none exists yet. Called from `write()` so the first * `wrangler login --use-keyring` is fully bootstrapping. */ private ensureKey; } /** * Per-consumer configuration for the credential-storage resolver. * * Captured by {@link createCredentialStorageContext} in a closure so the * returned `storage` adapter and `getActiveStore` function can both * re-resolve the active store on every call without re-reading shared * mutable module state. */ interface CredentialStorageContext { /** * Keyring service identifier (e.g. `"wrangler"`). Becomes the `-s` * argument to `/usr/bin/security`, the `service` attribute for * `secret-tool`, and the `service` argument to `@napi-rs/keyring`'s * `Entry`. Must be non-empty. */ serviceName: string; /** * The consumer's global config directory (e.g. wrangler's * `~/.wrangler`), resolved lazily on every credential operation. * * The client owns where its config lives — `cf` uses a different global * config path than wrangler — so `@cloudflare/workers-auth` never resolves * it itself. A getter (rather than a captured string) is required because * consumers create this context once at module load while tests re-stub * `HOME` / `XDG_CONFIG_HOME` per case, so the path must be re-read on each * call. The credential files (`.toml` / `.enc`) and the Windows keyring * binding all live under this directory. */ getConfigPath: () => string; /** * Whether the user has opted into keyring storage. Consulted on every * credential read/write so runtime preference changes (e.g. a user * toggling the option mid-session) take effect. */ isKeyringEnabled: () => boolean; /** Drop-in replacement for the consumer's logger singleton. */ logger: OAuthFlowLogger; /** Whether the process should not prompt the user. */ isNonInteractiveOrCI: () => boolean; /** * Login command for error-message templating, e.g. `"wrangler login"`. * Defaults to `"your CLI login"` when omitted. */ loginCommand?: string; /** * On-disk format of the plaintext credentials file (`.toml` / `.json`). * Defaults to TOML for wrangler; cf and other CLIs pass JSON. The encrypted * `.enc` sibling is format-independent (its payload is opaque ciphertext), * but the format still governs the plaintext file extension and the * plaintext→encrypted migration read. */ format?: FileFormat; } /** * Bundle returned by {@link createCredentialStorageContext}. * * - `storageFactory`: maps an auth profile to an {@link AuthConfigStorage} * adapter that delegates to that profile's active {@link CredentialStore} * on every method call. Pass this as `ctx.storageFactory` to * {@link createOAuthFlow}, which calls it with the active profile on every * credential access. * - `getActiveStore`: the live `CredentialStore` lookup for a given profile, * suitable for `whoami`-style consumers that want to call `describe()`. * * Both surfaces are wired against the same closure, so a runtime preference * flip (e.g. `wrangler login --no-use-keyring`) is observable through both * on the very next call. The profile argument selects which profile's files * / keyring entry the resolved store reads and writes. */ interface CredentialStorageBundle { storageFactory: (profile?: string) => AuthConfigStorage; getActiveStore: (profile?: string) => CredentialStore; } /** * Build a credential-storage bundle for a consumer (wrangler, future * Cloudflare CLIs). * * The bundle's `storage` is an `AuthConfigStorage` that re-resolves the * underlying store on every read/write/clear/path call. Selection order * (highest precedence first): * * 1. `CLOUDFLARE_AUTH_USE_KEYRING=false` env var — forces the file store. * 2. `CLOUDFLARE_AUTH_USE_KEYRING=true` env var — forces keyring storage; * failures throw rather than soft-falling-back. * 3. `isKeyringEnabled()` callback (the consumer's persistent preference) — * uses keyring storage; failures soft-fall-back with a one-time warning. * 4. Otherwise — defaults to the plaintext file store. * * The env var and the `isKeyringEnabled` callback are re-read on every * call so runtime preference changes take effect without rebuilding the * storage layer. */ declare function createCredentialStorageContext(context: CredentialStorageContext): CredentialStorageBundle; /** * Outcome of {@link scrubEncryptedCredentials}, so callers can tailor their * messaging (e.g. warn that a keyring entry may remain). */ interface ScrubEncryptedCredentialsResult { /** * Whether the keyring backend was *reachable* — i.e. a `KeyProvider` * resolved for this platform. When `true`, the encrypted store's `clear()` * removed the `.enc` file (and any plaintext `.toml`) and attempted to * delete the keyring key. When `false`, only the `.enc` file was removed * best-effort and a keyring entry (if one exists) was left behind. * * Note this reflects reachability, not that every operation succeeded: the * key deletion is best-effort (see `EncryptedFileCredentialStore.clear()`), * so in the rare case a reachable keyring fails mid-delete the `.enc` * ciphertext is still gone and only a bare, unusable key could linger. */ backendAvailable: boolean; /** Whether an encrypted `.enc` file existed before the scrub. */ encryptedFileExisted: boolean; } /** * Best-effort removal of a profile's encrypted credentials (`.enc` file) and * the keyring entry holding its encryption key. * * Shared by the `--no-use-keyring` opt-out (default profile) and * `wrangler auth delete ` (named profile) so both clear the encrypted * backend the same way, independent of the current keyring preference (a * profile may have been encrypted in a previous session even though keyring * storage is currently disabled). * * When the keyring backend is reachable, the encrypted store's `clear()` * removes the `.enc` file *and* the keyring key (and any plaintext * `.toml`). When it isn't (Linux without `secret-tool`, Windows without the * binding, an unsupported platform), the `.enc` file is removed best-effort * and `backendAvailable` is `false` so the caller can warn that the keyring * entry may remain. This never attempts a (Windows) binding install — a scrub * must not block on provisioning a backend it is trying to tear down. */ declare function scrubEncryptedCredentials(options: { serviceName: string; configPath: string; profile?: string; format?: FileFormat; }): ScrubEncryptedCredentialsResult; /** * Reset module-level per-session resolver flags (memoized warnings, the * Windows install-failed latch). * * Tests use this to start each case from a clean slate. In production * the flags reset naturally when the wrangler process exits. */ declare function resetCredentialStorageState(): void; /** * Alias kept for tests that previously called this to fully tear down * both the configuration and the session flags. With the per-consumer * configuration captured in `createCredentialStorageContext`, this now * does the same thing as {@link resetCredentialStorageState}: clear the * session flags. */ declare const clearCredentialStorageState: typeof resetCredentialStorageState; /** * Resolve the keyring account name for the given auth profile. * * Shares {@link resolveAuthProfileBaseName} with the file paths so the * keyring entry tracks the same identity as the on-disk files: the default * profile gets `default` in production or the environment name otherwise * (so a single OS user can hold production and staging credentials * side-by-side), while a named profile gets the profile name. This means * each profile holds its own encryption key, so clearing one profile's * credentials never disturbs another's. * * The service name is consumer-configured (passed to each `KeyProvider`'s * constructor) — this account-name derivation is Cloudflare-wide and stays * inside `@cloudflare/workers-auth`. */ declare function getKeyringAccountName(profile?: string): string; /** Signature of the `/usr/bin/security` invoker. Overridable for tests. */ type MacSecurityCommandRunner = (args: string[], options?: { input?: string; }) => SpawnSyncReturns; /** * Override the `/usr/bin/security` invoker for tests. Pass `undefined` to * restore the default real-process runner. */ declare function setMacSecurityCommandRunner(fn: MacSecurityCommandRunner | undefined): void; /** * macOS Keychain backend that stores the encryption key for the active * {@link EncryptedFileCredentialStore} via the `/usr/bin/security` CLI. * * The `security` binary is part of every macOS install so this path has * zero install cost. The `serviceName` is consumer-provided so different * Cloudflare CLIs (wrangler, future tools) can coexist on the same * keychain without colliding. * * Trade-off: `add-generic-password -w ` puts the secret on the * argv of a short-lived subprocess, briefly visible to other processes * running as the same user (e.g. via `ps`). This is the same trade-off * accepted by `git credential-osxkeychain`. Because the secret here is * only the 32-byte encryption key (not the OAuth tokens themselves), the * exposure window is narrower than the previous direct-keyring design. */ declare class MacSecurityKeyProvider implements KeyProvider { private readonly serviceName; private readonly profile?; constructor(serviceName: string, profile?: string | undefined); getKey(): Uint8Array | undefined; setKey(key: Uint8Array): void; deleteKey(): void; describe(): string; } /** Signature of the `secret-tool` invoker. Overridable for tests. */ type LinuxSecretToolRunner = (args: string[], options?: { input?: string; }) => SpawnSyncReturns; /** * Override the `secret-tool` invoker for tests. Pass `undefined` to restore * the default real-process runner. Resets the memoized * {@link probeSecretTool} result so the next call re-probes through the * new runner. */ declare function setLinuxSecretToolRunner(fn: LinuxSecretToolRunner | undefined): void; /** * Probe whether `secret-tool` is callable in the current environment. * * Returns `true` when `secret-tool` could be spawned at all, whatever its * exit status. libsecret's `secret-tool` has no `--version` flag: it prints * its usage and exits 2, so the exit status says nothing about whether the * tool is installed. Only a failure to spawn the process (e.g. `ENOENT` * when it is not on `PATH`) means it is missing. The probe does not * exercise the keyring backend itself — a missing D-Bus session surfaces * on the first real read/write rather than every consumer invocation, so * we avoid the extra latency on every command for users whose desktop * session is fully working. * * The result is memoized per-process: `secret-tool` is not going to be * uninstalled mid-command, and the resolver re-resolves the active store * on every credential operation (see `resolver.ts`), so caching keeps the * probe off the hot path. Tests reset the cache via * {@link setLinuxSecretToolRunner}. */ declare function probeSecretTool(): boolean; /** * Linux backend that stores the encryption key via libsecret's * `secret-tool` CLI. * * The key is passed to `secret-tool store` via stdin so it never appears * on the subprocess argv. Lookup writes the key envelope to stdout, which * is captured by `spawnSync`. * * `secret-tool` is part of the `libsecret-tools` package on most Linux * distros. The resolver in {@link "../resolver"} probes for its presence * and surfaces actionable install hints when missing; this class assumes * the tool is available. */ declare class LinuxSecretToolKeyProvider implements KeyProvider { private readonly serviceName; private readonly profile?; constructor(serviceName: string, profile?: string | undefined); getKey(): Uint8Array | undefined; setKey(key: Uint8Array): void; deleteKey(): void; describe(): string; } /** * Backend that stores the encryption key via `@napi-rs/keyring`'s * native `Entry` class. * * Used on Windows once the binding has been lazy-installed (via the * resolver), and by tests on every platform that register an in-memory * `KeyringEntryFactory` via {@link setKeyringEntryFactory}. * * On Windows the binding talks to the Credential Manager wincred API. * On macOS / Linux (when used by tests), the test factory short-circuits * the lazy load so no real keychain is touched. */ declare class NapiKeyringKeyProvider implements KeyProvider { private readonly serviceName; private readonly installDir; private readonly profile?; /** * @param serviceName keyring service identifier (e.g. `"wrangler"`). * @param installDir directory hosting the lazy-installed `@napi-rs/keyring` * binding, derived from the consumer's config path. * @param profile the auth profile (selects the keyring account name). */ constructor(serviceName: string, installDir: string, profile?: string | undefined); private entry; getKey(): Uint8Array | undefined; setKey(key: Uint8Array): void; deleteKey(): void; describe(): string; } /** * Pinned version of `@napi-rs/keyring` that gets installed lazily on * Windows when the user opts into keyring storage. * * Hard-coded so we stamp the same version into both the user-facing * "install it globally" hint and the actual `npm install` command — * ensuring CI users running the global-install workaround see exactly * the version we tested against. */ declare const PINNED_KEYRING_VERSION = "1.3.0"; /** Signature of the `npm` invoker. Overridable for tests. */ type NpmRunner = (args: string[]) => SpawnSyncReturns; /** * Override the `npm` invoker for tests. Pass `undefined` to restore the * default real-process runner. Resets the memoized * {@link findKeyringBinding} cache so the next call re-probes through * the new runner. */ declare function setNpmRunner(fn: NpmRunner | undefined): void; /** * Directory used to host the lazy-installed `@napi-rs/keyring` binding, under * the consumer-provided global config directory (`configPath`). A sibling of * the credentials dir so `runInTempDir()` test fixtures (which redirect `HOME` * / `XDG_CONFIG_HOME`) isolate the install dir alongside everything else stored * under the config path. * * `configPath` is supplied by the client (wrangler, or a future `cf` CLI) — the * same value used for the credential files — so each CLI's native binding lives * under its own config directory rather than a hard-coded wrangler location. */ declare function getKeyringInstallDir(configPath: string): string; /** * Locate an installed `@napi-rs/keyring` binding usable from this process. * * Search order: * 1. The private install dir written by {@link installKeyringBindingSync}. * 2. The user's global npm root, so a manual `npm install -g * @napi-rs/keyring` works in CI environments where the lazy install * path is unavailable. * * A candidate only counts when it actually loads (see * {@link canLoadKeyringBinding}) — a half-installed binding is reported as * absent so the caller reinstalls it, rather than being trusted forever on the * strength of an `index.js` that cannot be required. * * Returns `null` when no binding is available; callers handle the missing * binding case explicitly so they can surface remediation instructions. * * The result is memoized per-process, keyed by `installDir`. The resolver * calls this on every credential operation, so without caching we would spawn * `npm root -g` each time the binding is not in the lazy dir. The cache is * invalidated by {@link installKeyringBindingSync} on a successful install and * by {@link setNpmRunner} for test isolation. */ declare function findKeyringBinding(installDir: string): string | null; /** * Install `@napi-rs/keyring` into the private install dir using the user's * `npm`. * * Throws a {@link UserError} when `npm` cannot be spawned, returns a non-zero * exit code, or exits cleanly without leaving a loadable binding behind, so * callers can surface actionable remediation hints rather than a raw stack * trace. */ declare function installKeyringBindingSync(installDir: string): void; /** * Minimal slice of `@napi-rs/keyring`'s `Entry` class that {@link * NapiKeyringKeyProvider} depends on. * * Defined locally so we can load the underlying module lazily — the native * binary must not be required (and `dlopen`-ed) unless the user has * actually opted into keyring storage. */ interface KeyringEntry { setPassword(password: string): void; getPassword(): string | null; deletePassword(): boolean; } /** Factory signature used by `NapiKeyringKeyProvider` to create entries. */ type KeyringEntryFactory = (service: string, account: string) => KeyringEntry; /** * Override the keyring entry factory used by `NapiKeyringKeyProvider`. * * Tests use this to inject an in-memory fake so they never touch the * developer machine's real keychain. Pass `undefined` to restore the * default (lazy dynamic require). */ declare function setKeyringEntryFactory(factory: KeyringEntryFactory | undefined): void; /** * Outcome of trying to create a `KeyProvider` for the current platform. * * - `available`: a provider exists and is ready to use immediately. * - `needs-install`: a provider is in principle supported but the local * binding/tool isn't installed yet. The resolver decides whether to * attempt an interactive install or surface remediation. * - `unsupported`: the platform has no `KeyProvider` implementation * (e.g. FreeBSD). The resolver falls back to file storage. */ type KeyProviderResolution = { kind: "available"; provider: KeyProvider; } | { kind: "needs-install"; install: () => void; afterInstall: () => KeyProvider; } | { kind: "unsupported"; }; /** * Inject a `KeyProvider` factory for testing. Pass `undefined` to restore * the real per-platform resolution. The factory receives the auth profile * so profile-aware tests can hand back a provider scoped to that profile. */ declare function setKeyProviderFactoryForTesting(factory: ((serviceName: string, profile?: string) => KeyProvider) | undefined): void; /** * Resolve the appropriate `KeyProvider` for the current platform. * * Pure resolution: this function never spawns long-running work, never * installs anything, and never logs. The "needs-install" arm returns * thunks the caller can invoke once it has decided how to handle the * missing-binding case (interactive install vs. hard-error). * * `configPath` is the consumer's global config directory; on Windows it locates * the lazy-installed `@napi-rs/keyring` binding under the CLI's own config dir. * The macOS / Linux backends don't use it. */ declare function resolveKeyProvider(serviceName: string, profile: string | undefined, configPath: string): KeyProviderResolution; /** * Self-documenting algorithm identifier stamped into the on-disk envelope. */ declare const ALGORITHM_LABEL = "AES-256-GCM"; /** * Envelope format for the encrypted payload written to disk. * * The `v` field lets us evolve the format (e.g. switch algorithm, add key * IDs) without breaking older readers — they can detect an unknown version * and refuse to decrypt rather than fail in an obscure way deep inside * the cipher. */ interface EncryptedEnvelope { /** Schema version. Bump on incompatible changes. */ v: 1; /** Algorithm label. Informational; the reader still validates against {@link CIPHER_NAME}. */ alg: typeof ALGORITHM_LABEL; /** Base64-encoded 12-byte IV. */ iv: string; /** Base64-encoded 16-byte GCM auth tag. */ tag: string; /** Base64-encoded ciphertext. */ ciphertext: string; } /** * Generate a fresh 32-byte symmetric key suitable for AES-256. * * Uses `node:crypto.randomBytes`, which is a thin wrapper over the OS * CSPRNG (`/dev/urandom` on Unix, `BCryptGenRandom` on Windows). */ declare function generateKey(): Uint8Array; /** * Encrypt a UTF-8 plaintext into an {@link EncryptedEnvelope} using * AES-256-GCM with a freshly-generated IV. * * GCM is authenticated encryption: the auth tag is computed over the * ciphertext and validated by {@link decryptString}. Any tampering with * the IV, tag, or ciphertext causes decryption to throw. * * IV uniqueness is critical for GCM security — generating a fresh random * IV per call (rather than counter-based) keeps callers from accidentally * reusing one when the same key encrypts multiple payloads. */ declare function encryptString(plaintext: string, key: Uint8Array): EncryptedEnvelope; /** * Decrypt an {@link EncryptedEnvelope} back into the original UTF-8 * plaintext. * * @throws {Error} when the key length is wrong, the envelope version is * unknown, the IV/tag lengths don't match what AES-GCM expects, or the * GCM auth tag fails to verify (tampering or wrong key). */ declare function decryptString(envelope: EncryptedEnvelope, key: Uint8Array): string; /** * Type-narrow `unknown` to an {@link EncryptedEnvelope}, returning * `undefined` when the input doesn't match the schema. * * Used by {@link EncryptedFileCredentialStore.read} to handle corrupted / * truncated / pre-format-v1 files as "no credentials stored" rather than * crashing the consumer. */ declare function parseEncryptedEnvelope(raw: unknown): EncryptedEnvelope | undefined; export { AuthConfigStorage, type CredentialStorageBundle, type CredentialStorageContext, CredentialStore, type EncryptedEnvelope, EncryptedFileCredentialStore, FileCredentialStore, type KeyProvider, type KeyProviderResolution, type KeyringEntry, type KeyringEntryFactory, LinuxSecretToolKeyProvider, type LinuxSecretToolRunner, type MacSecurityCommandRunner, MacSecurityKeyProvider, NapiKeyringKeyProvider, type NpmRunner, OAuthFlowLogger, PINNED_KEYRING_VERSION, PKCE_CHARSET, type ScrubEncryptedCredentialsResult, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, UserAuthConfig, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, decryptString, domainUsesAccess, encryptString, findKeyringBinding, generateKey, generateVerificationUrl, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner };