#!/usr/bin/env bash
#
# arch-install bootstrap stub. Served publicly from https://arch.abtech.sh
# and contains NO secrets.
#
#     curl -fsSL https://arch.abtech.sh | bash
#
# Fetches a read-only deploy key from the Worker (gated by an 8-digit TOTP
# code), clones the private repository with it, and hands over to boot.sh.
set -euo pipefail

ENDPOINT=${ENDPOINT:-https://arch.abtech.sh}
REPO_SSH=${REPO_SSH:-git@github.com:adi961/arch-install.git}
REPO_BRANCH=${REPO_BRANCH:-main}
DEST=${DEST:-/root/arch-install}

say() { printf '==> %s\n' "$*" >&2; }
die() { printf 'err  %s\n' "$*" >&2; exit 1; }

# ---------------------------------------------------------------------------
# Interactive input must come from the terminal.
#
# This script is designed to be piped into bash, which makes stdin the SCRIPT.
# A bare `read` would consume the next line of this file as the answer and then
# never execute it. lib/common.sh solves this the same way, but that file lives
# in the repository we have not downloaded yet.
# ---------------------------------------------------------------------------

{ : </dev/tty; } 2>/dev/null || die "no terminal available for the code prompt.
    Download the script first, then run it:
        curl -fsSL $ENDPOINT -o install.sh && bash install.sh"

# ---------------------------------------------------------------------------
# Preconditions
# ---------------------------------------------------------------------------

[[ $(id -u) -eq 0 ]] || die "run as root (you are on the Arch ISO, so you already are)"

# curl and tar ship on the Arch ISO; git does NOT. Deploy keys are SSH-only, so
# a clone is the only way to use one and git has to be fetched first. The
# mirrors are needed moments later for pacstrap anyway.
if ! command -v git >/dev/null 2>&1; then
    say "installing git (absent from the Arch ISO)"
    pacman -Sy --noconfirm --needed git >/dev/null 2>&1 \
        || die "could not install git. Check the network and the mirrorlist."
fi

# ---------------------------------------------------------------------------
# Pin GitHub's host keys
#
# Public keys, so nothing secret is shipped here - but it means the clone
# cannot be silently intercepted, and there is no trust-on-first-use prompt.
# Verified against https://api.github.com/meta on 2026-08-12:
#   ed25519  SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU
#   ecdsa    SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM
#   rsa      SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s
# ---------------------------------------------------------------------------

WORK=$(mktemp -d)
# Shred rather than delete: the deploy key passes through this directory.
cleanup() {
    if [[ -n ${WORK:-} && -d $WORK ]]; then
        find "$WORK" -type f -exec shred -u {} + 2>/dev/null || true
        rm -rf "$WORK"
    fi
}
trap cleanup EXIT

cat >"$WORK/known_hosts" <<'KNOWN_HOSTS'
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
KNOWN_HOSTS

# ---------------------------------------------------------------------------
# Fetch the deploy key
# ---------------------------------------------------------------------------

printf '8-digit code from your authenticator: ' >&2
read -r CODE </dev/tty
printf '\n' >&2
[[ $CODE =~ ^[0-9]{8}$ ]] || die "expected 8 digits"

say "authenticating"
HTTP=$(curl -fsS --proto '=https' --tlsv1.2 --max-time 30 \
    -H "X-Install-Code: $CODE" \
    -o "$WORK/deploy_key" -w '%{http_code}' \
    "$ENDPOINT/key" 2>/dev/null) || {
    # curl -f gives no body on error, so report what the status means.
    case ${HTTP:-000} in
        401) die "invalid or expired code" ;;
        429) die "locked out after too many failed attempts; it clears within the hour" ;;
        503) die "the endpoint is not configured (missing secret)" ;;
        000) die "could not reach $ENDPOINT - check the network" ;;
        *)   die "unexpected response from $ENDPOINT (HTTP $HTTP)" ;;
    esac
}

chmod 0600 "$WORK/deploy_key"
ssh-keygen -y -f "$WORK/deploy_key" >/dev/null 2>&1 \
    || die "what the endpoint returned is not a usable private key"

# ---------------------------------------------------------------------------
# Clone and hand over
# ---------------------------------------------------------------------------

say "cloning $REPO_SSH ($REPO_BRANCH)"
rm -rf "$DEST"
GIT_SSH_COMMAND="ssh -i $WORK/deploy_key -o IdentitiesOnly=yes \
    -o UserKnownHostsFile=$WORK/known_hosts -o StrictHostKeyChecking=yes" \
    git clone --depth 1 --branch "$REPO_BRANCH" "$REPO_SSH" "$DEST" 2>&1 \
    | sed 's/^/    /' >&2 \
    || die "clone failed - is the deploy key still authorised on the repository?"

# The key has done its job; remove it before handing over rather than relying
# only on the exit trap.
shred -u "$WORK/deploy_key" 2>/dev/null || rm -f "$WORK/deploy_key"

say "starting the installer"
exec "$DEST/boot.sh" "$@"
