export type TunnelProvider = "cloudflared" | "ngrok";
export interface TunnelOptions {
    tunnelName?: string;
    tunnelHostname?: string;
    /**
     * Path to an isolated `cert.pem` for `TUNNEL_ORIGIN_CERT`. When set, all
     * `cloudflared` invocations for the named tunnel will use this cert instead
     * of `~/.cloudflared/cert.pem`. Used by dev profiles to avoid polluting the
     * user's personal Cloudflare configuration. When undefined, behaviour is
     * identical to before (the spawn() `env` key is omitted entirely).
     */
    tunnelOriginCert?: string;
    /**
     * Path to an isolated cloudflared `config.yml`. When set, the named tunnel
     * process is launched with `--config <path>` and ingress rules are written
     * to this file. When undefined, `~/.cloudflared/config.yml` is used.
     * Must be paired with tunnelOriginCert (enforced by ObsConfigSchema), OR
     * with `tunnelId` when running in runtime-credentials mode.
     */
    tunnelConfigPath?: string;
    /**
     * Tunnel UUID known ahead of time — typically delivered via the
     * onboarding-service heartbeat `credentialBundle.body.tunnel` payload.
     *
     * When set, the named-tunnel startup path skips every `cloudflared` call
     * that relies on `cert.pem` (`tunnel info`, `tunnel route dns`), since
     * the agent no longer provisions the tunnel locally. The resulting
     * runtime only needs `--config <path> run <tunnelName>`, with
     * `credentials-file` pointing at the `{UUID}.json` blob already on disk.
     *
     * Must be paired with `tunnelConfigPath` so cloudflared can locate the
     * profile-scoped config.
     */
    tunnelId?: string;
}
export interface TunnelResult {
    url: string;
    stop: () => Promise<void>;
}
/**
 * Discover legacy `cloudflared tunnel run <name>` processes currently
 * running on this host. The match is intentionally narrow:
 *   - only `cloudflared` command lines
 *   - only lines containing `tunnel run`
 *   - only the exact tunnel name as a standalone arg
 *
 * Exposed for tests. Callers in production should prefer
 * `stopLegacyNamedTunnelProcesses()` below, which wraps this with a
 * terminate-and-confirm cycle.
 */
export declare function findLegacyNamedTunnelPids(tunnelName: string): number[];
/**
 * Options for {@link stopLegacyNamedTunnelProcesses}. Exposed primarily
 * so tests can drive the terminate/poll/force-kill cycle deterministically.
 */
export interface StopLegacyNamedTunnelOptions {
    /** Total time budget for graceful shutdown after SIGTERM. Default 8s. */
    gracefulTimeoutMs?: number;
    /** Poll interval while waiting for the process to exit. Default 100ms. */
    pollIntervalMs?: number;
    /** Grace window after SIGKILL before giving up. Default 2s. */
    forceKillTimeoutMs?: number;
}
export interface StopLegacyNamedTunnelResult {
    /** PIDs we confirmed exited (either gracefully or after SIGKILL). */
    stopped: number[];
    /** PIDs that were still alive after SIGTERM + SIGKILL + timeouts. */
    survived: number[];
}
/**
 * Migration handoff for a pre-existing legacy `cloudflared tunnel run
 * <name>` process. Sends SIGTERM, polls for exit, escalates to SIGKILL if
 * the process does not exit within `gracefulTimeoutMs`, and only resolves
 * once every targeted PID is confirmed gone (or the force-kill window has
 * elapsed). This prevents the profile-managed connector the caller is
 * about to start from racing an inherited legacy connector for the same
 * tunnel UUID.
 */
export declare function stopLegacyNamedTunnelProcesses(tunnelName: string, opts?: StopLegacyNamedTunnelOptions): Promise<StopLegacyNamedTunnelResult>;
export declare function isCloudflareIPv4(ip: string): boolean;
export declare function startTunnel(port: number, provider: TunnelProvider, options?: TunnelOptions): Promise<TunnelResult>;
//# sourceMappingURL=tunnel.d.ts.map