/**
 * Serialize a resolved env map to `.env` lines that round-trip losslessly through
 * `parseDotenv` on the remote: `KEY="VALUE"`. parseDotenv strips exactly one outer
 * quote pair and takes the inner bytes verbatim (no unescaping), so any single-line
 * value survives unchanged with no escaping. Newlines would break its line-based
 * parse, so multi-line values are rejected rather than silently corrupted.
 */
export declare function bundleEnvToDotenv(env: Record<string, string>): string;
/** Where the bundle should live ON THE REMOTE. */
export type RemoteBackend = 'keychain' | 'file';
/** A bundle read once, ready to push to any number of hosts. */
export interface ResolvedBundleForPush {
    /** key -> value. Never logged; only its KEY NAMES are ever surfaced. */
    env: Record<string, string>;
    /** The same values as a dotenv blob, shipped over ssh stdin (never argv). */
    dotenv: string;
    keyCount: number;
}
export interface PushBundleOptions {
    remoteBackend: RemoteBackend;
    /** Overwrite a key that already exists on the remote. */
    force?: boolean;
    /**
     * Ignored. File-backend export never forwards AGENTS_SECRETS_PASSPHRASE
     * (PHNX-2371); the remote auto-provisions its own machine-local key.
     * Kept on the options type so existing callers that passed one still compile.
     */
    passphrase?: string;
    /** Label for the audit trail — `export --device` vs `fleet apply`. */
    operation: string;
    /** Preserve an automation account's permanent prompt-free policy remotely. */
    policyNever?: boolean;
    /** Permit a human-invoked push to read locally without requiring the agent broker. */
    agentOnly?: boolean;
    /** Non-secret literals whose bundle value kind must survive the dotenv transport. */
    literalValues?: Record<string, string>;
    /** Per-SSH-operation deadline. Async daemon callers must set this explicitly. */
    timeoutMs?: number;
}
export interface PushBundleResult {
    ok: boolean;
    host: string;
    bundle: string;
    keyCount: number;
    /** One line for the caller to render. Never contains a secret value. */
    message: string;
}
export interface LiteralRestorePlan {
    key: string;
    removeArgs: string[];
    addArgs: string[];
}
/** Preserve the literal-vs-secret schema that dotenv transport cannot encode. */
export declare function planLiteralRestoration(bundle: string, literalValues?: Record<string, string>): LiteralRestorePlan[];
/**
 * Read and resolve a bundle once, for pushing to one or more hosts.
 *
 * `keyMode: 'storage'` is fixed — a push always sends storage-shaped values.
 *
 * `agentOnly` is the caller's to decide, and it is NOT a security level: it
 * selects the broker-only read (fail fast with the `agents secrets unlock` hint)
 * over the interactive read (macOS may raise a Touch ID sheet). The headless
 * guard exists because an AGENT LAUNCH must never enumerate the keychain — a
 * per-bundle prefix becomes a broad `agents-cli.` scan after service-name
 * hashing, and macOS evaluates unrelated biometry ACLs during it, one sheet per
 * installed version (bundles.ts, RUSH-2440). A human at a TTY is not that case:
 * they can answer one prompt, and the interactive sibling reads (`view --reveal`,
 * `exec`) already let them. NOT `get` — it is unconditionally `agentOnly` on
 * purpose, because prompting would hang a `$(agents secrets get …)` capture
 * mid-pipeline (SEC-13b). It defaults to `true` so an automated caller that says
 * nothing stays broker-only.
 */
export declare function resolveBundleForPush(bundle: string, caller: string, opts?: {
    agentOnly?: boolean;
}): ResolvedBundleForPush;
/**
 * WHICH transport a (backend, target-OS) pair selects, and the exact bytes it
 * will send. One of four outcomes, and picking the wrong one is silent: a
 * Windows target handed a POSIX `bash -lc` produces garbage, and a Windows
 * target handed `--from -` hangs forever on a stdin the `agents.ps1` shim never
 * forwards. Neither shows up as a failed ssh, so the selection is the thing
 * worth pinning.
 *
 * Separated from execution so it is decidable without a network: the branch is
 * chosen from the device registry alone, and `pushResolvedBundleToHost` below
 * does nothing but run what this returns.
 */
export type PushTransport = 
/** No supported command exists for this pair — fail loud, never a wrong path. */
{
    kind: 'refuse';
    message: string;
}
/**
 * A command sent over the raw ssh engine, with the .env on stdin. `multiplex`
 * is always `false`: a push ships credential bytes, so its connection must not
 * reuse — or leave behind — a persistent authenticated control master to the
 * destination the way the default fan-out connections do (RUSH-2527). This
 * mirrors the `--copy-creds` dispatch posture (`multiplex: !opts.copyCreds`).
 */
 | {
    kind: 'ssh';
    remoteCmd: string;
    input: string;
    multiplex: false;
}
/** The OS-aware `agents secrets` wrapper, the READ inverse's own path. Never multiplexed — see the `ssh` kind. */
 | {
    kind: 'remote-secrets';
    args: string[];
    input: string;
    multiplex: false;
};
/** Choose the transport for one push. Pure: registry read in, plan out. */
export declare function planPushTransport(resolved: ResolvedBundleForPush, bundle: string, host: string, opts: PushBundleOptions): PushTransport;
/**
 * Push an already-resolved bundle to ONE host.
 *
 * Drives the remote's own `agents secrets import --from -`, so the values land
 * in the remote's chosen backend and the .env is read off ssh stdin rather than
 * parsed by a remote shell. `import` auto-creates the bundle.
 */
export declare function pushResolvedBundleToHost(resolved: ResolvedBundleForPush, bundle: string, host: string, opts: PushBundleOptions): PushBundleResult;
/** Resolve and push in one call — for a single host. */
export declare function pushBundleToHost(bundle: string, host: string, opts: PushBundleOptions): PushBundleResult;
/**
 * Async, kill-bounded push for daemon services. It preserves the foreground
 * primitive's transport, read-back verification, and literal restoration; only
 * the SSH execution strategy differs.
 */
export declare function pushResolvedBundleToHostAsync(resolved: ResolvedBundleForPush, bundle: string, host: string, opts: PushBundleOptions): Promise<PushBundleResult>;
/** Resolve locally once, then run the daemon-safe async push. */
export declare function pushBundleToHostAsync(bundle: string, host: string, opts: PushBundleOptions): Promise<PushBundleResult>;
