/**
 * Provider-agnostic single-box provisioning.
 *
 * `createBoxProvisioner` gives deploy scripts one interface — ensure a named
 * box exists (running, reachable, firewall open, SSH key authorized, bootstrap
 * script run) and tear it down again — regardless of whether the box lives on
 * Hetzner Cloud or AWS EC2. Idempotent like the underlying `ensure*` helpers:
 * re-running converges instead of duplicating resources.
 *
 * SSH access is normalized to `root@<publicIp>`: the public key is injected
 * via cloud-init (`disable_root: false` plus an authorized_keys append) so the
 * same `sshExec(host, cmd)` calls work on both providers, even though AWS
 * Ubuntu images default to the `ubuntu` user.
 */
import type { EC2Client } from '../../aws/ec2';
import type { SSMClient } from '../../aws/ssm';
import type { HetznerClient } from '../hetzner/client';
export type BoxProviderName = 'hetzner' | 'aws';
export interface BoxPort {
    protocol: 'tcp' | 'udp' | 'icmp';
    /** Port number; omit for icmp. */
    port?: number;
}
export interface BoxSpec {
    /** Resource name; also names the firewall/security group (`<name>-fw`/`<name>-sg`). */
    name: string;
    /** Provider-native size (Hetzner server type like `cx23`, EC2 instance type like `t3.micro`). */
    size: string;
    /** Hetzner image name or an `ami-...` id. Defaults to Ubuntu 24.04 on both providers. */
    image?: string;
    /** Hetzner location (e.g. `fsn1`). AWS placement follows the provisioner's region. */
    location?: string;
    /** Ingress to open in addition to tcp/22. */
    ports?: BoxPort[];
    /** OpenSSH public key authorized for root. */
    sshPublicKey: string;
    /** Plain bash bootstrap script, run once at first boot via cloud-init. */
    bootstrapScript?: string;
    labels?: Record<string, string>;
}
export interface ProvisionedBox {
    provider: BoxProviderName;
    id: string;
    name: string;
    publicIp: string;
    created: boolean;
}
export interface BoxProvisioner {
    readonly provider: BoxProviderName;
    ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
    /** Tear down the box and its firewall/security group. */
    destroyBox(name: string): Promise<{
        destroyed: string[];
    }>;
}
/** SSM parameter for the current Ubuntu 24.04 amd64 gp3 AMI (Canonical-published). */
export declare const UBUNTU_2404_AMI_PARAM = "/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id";
/**
 * Cloud-config shared by both providers: root SSH access with the given key
 * (AWS Ubuntu images otherwise lock root and point at the `ubuntu` user) and
 * the optional bootstrap script.
 */
export declare function buildBoxUserData(spec: Pick<BoxSpec, 'sshPublicKey' | 'bootstrapScript'>): string;
export declare class HetznerBoxProvisioner implements BoxProvisioner {
    private client;
    readonly provider: 'hetzner';
    constructor(client: HetznerClient);
    ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
    destroyBox(name: string): Promise<{
        destroyed: string[];
    }>;
}
/** The EC2 surface the AWS provisioner uses (injectable for tests). */
export type BoxEc2Client = Pick<EC2Client, 'describeInstances' | 'describeSecurityGroups' | 'createSecurityGroup' | 'authorizeSecurityGroupIngress' | 'runInstances' | 'terminateInstances' | 'deleteSecurityGroup' | 'getInstance'>;
/** The SSM surface the AWS provisioner uses (injectable for tests). */
export type BoxSsmClient = Pick<SSMClient, 'getParameter'>;
export interface AwsBoxProvisionerOptions {
    ec2: BoxEc2Client;
    ssm: BoxSsmClient;
}
export declare class AwsBoxProvisioner implements BoxProvisioner {
    readonly provider: 'aws';
    private ec2;
    private ssm;
    constructor(options: AwsBoxProvisionerOptions);
    private findInstance;
    private waitForPublicIp;
    private ensureSecurityGroup;
    private resolveImage;
    ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
    destroyBox(name: string): Promise<{
        destroyed: string[];
    }>;
}
export interface CreateBoxProvisionerOptions {
    provider: BoxProviderName;
    /** Required for provider 'hetzner'. */
    hetzner?: HetznerClient;
    /** Required for provider 'aws'. */
    aws?: AwsBoxProvisionerOptions;
}
export declare function createBoxProvisioner(options: CreateBoxProvisionerOptions): BoxProvisioner;
