#!/bin/bash
# install-latest.sh installs the current signed Barndoor MDM package.
#
# Deploy this script once as a root-level, recurring remediation script in an
# MDM. It is intentionally provider-neutral: Iru can use it as a continuous
# audit/remediation script and Rippling can schedule it as a recurring script.
# The release workflow is the only publisher of the manifest it consumes.
set -euo pipefail

# MDM agents should provide a safe environment, but this script executes as
# root and must not inherit a user-controlled command search path.
export PATH="/usr/bin:/bin:/usr/sbin:/sbin"

readonly DOWNLOAD_HOST="downloads.barndoor.ai"
# Release channel. "stable" (default) follows mdm/latest.json, which only moves
# when a version is promoted through the GUI Promote workflow. "edge" follows
# mdm/edge/latest.json, which every gui/v* release rewrites; use it for
# internal fleets that should act as the canary for customer fleets.
# Select with `--channel edge`, a bare `edge` argument, or
# BARNDOOR_MDM_CHANNEL=edge in the script's environment.
CHANNEL="${BARNDOOR_MDM_CHANNEL:-stable}"
readonly APP_GUI="/Applications/Barndoor.app/Contents/MacOS/Barndoor"
# Executable name before the rename to "Barndoor"; still present on Macs that
# installed an older pkg, so the version check must recognise it.
readonly LEGACY_APP_GUI="/Applications/Barndoor.app/Contents/MacOS/barndoor-gui"
readonly PACKAGE_ID="ai.barndoor.app"
readonly INSTALLER_IDENTITY="Developer ID Installer: Barndoor AI, Inc. (547SWHX99F)"

temp_dir=""

cleanup() {
  if [[ -n "$temp_dir" && -d "$temp_dir" ]]; then
    rm -rf "$temp_dir"
  fi
}
trap cleanup EXIT HUP INT TERM

fail() {
  echo "barndoor-mdm-update: $*" >&2
  exit 1
}

require_root_macos() {
  [[ "$(id -u)" -eq 0 ]] || fail "must run as root"
  [[ "$(uname -s)" == "Darwin" ]] || fail "macOS is required"
}

manifest_value() {
  local key="$1"
  /usr/bin/plutil -extract "$key" raw -o - "$temp_dir/latest.json"
}

valid_version() {
  # Reject leading zeroes as well as prerelease/version suffixes. That keeps
  # the arithmetic comparison below unambiguous on macOS's Bash 3.2.
  [[ "$1" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]
}

version_is_newer() {
  local wanted="${1#v}" installed="${2#v}"
  local wanted_major wanted_minor wanted_patch
  local installed_major installed_minor installed_patch
  IFS=. read -r wanted_major wanted_minor wanted_patch <<<"$wanted"
  IFS=. read -r installed_major installed_minor installed_patch <<<"$installed"

  if (( wanted_major != installed_major )); then
    (( wanted_major > installed_major ))
  elif (( wanted_minor != installed_minor )); then
    (( wanted_minor > installed_minor ))
  else
    (( wanted_patch > installed_patch ))
  fi
}

installed_version() {
  if [[ -x "$APP_GUI" ]]; then
    "$APP_GUI" --version
  elif [[ -x "$LEGACY_APP_GUI" ]]; then
    "$LEGACY_APP_GUI" --version
  fi
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --channel) [[ $# -ge 2 ]] || fail "--channel requires a value"; CHANNEL="$2"; shift 2 ;;
    --channel=*) CHANNEL="${1#*=}"; shift ;;
    stable|edge) CHANNEL="$1"; shift ;;
    *) fail "unknown argument: $1 (expected --channel stable|edge)" ;;
  esac
done

case "$CHANNEL" in
  stable) MANIFEST_URL="https://${DOWNLOAD_HOST}/barndoor-gui/mdm/latest.json" ;;
  edge) MANIFEST_URL="https://${DOWNLOAD_HOST}/barndoor-gui/mdm/edge/latest.json" ;;
  *) fail "unknown channel: $CHANNEL (expected stable or edge)" ;;
esac
readonly CHANNEL MANIFEST_URL

require_root_macos
temp_dir="$(mktemp -d /private/tmp/barndoor-mdm-update.XXXXXX)"

/usr/bin/curl --fail --location --proto '=https' --tlsv1.2 \
  --silent --show-error "$MANIFEST_URL" -o "$temp_dir/latest.json"

wanted_version="$(manifest_value version)"
package_url="$(manifest_value package_url)"
expected_sha256="$(manifest_value sha256)"
expected_size="$(manifest_value size)"
manifest_package_id="$(manifest_value package_id)"

valid_version "$wanted_version" || fail "manifest has an invalid version"
[[ "$manifest_package_id" == "$PACKAGE_ID" ]] || fail "manifest has an unexpected package ID"
[[ "$expected_sha256" =~ ^[0-9a-f]{64}$ ]] || fail "manifest has an invalid SHA-256"
[[ "$expected_size" =~ ^[1-9][0-9]*$ ]] || fail "manifest has an invalid package size"

expected_url="https://${DOWNLOAD_HOST}/barndoor-gui/${wanted_version}/Barndoor-${wanted_version}.pkg"
[[ "$package_url" == "$expected_url" ]] || fail "manifest has an unexpected package URL"

current_version="$(installed_version || true)"
if [[ -n "$current_version" ]]; then
  valid_version "$current_version" || fail "installed GUI returned an invalid version: $current_version"
  if [[ "$current_version" == "$wanted_version" ]]; then
    echo "barndoor-mdm-update: already at $current_version ($CHANNEL channel)"
    exit 0
  fi
  if ! version_is_newer "$wanted_version" "$current_version"; then
    echo "barndoor-mdm-update: installed $current_version is newer than manifest $wanted_version; skipping"
    exit 0
  fi
fi

package_path="$temp_dir/Barndoor-${wanted_version}.pkg"
/usr/bin/curl --fail --location --proto '=https' --tlsv1.2 \
  --silent --show-error "$package_url" -o "$package_path"

actual_sha256="$(/usr/bin/shasum -a 256 "$package_path" | /usr/bin/awk '{print $1}')"
[[ "$actual_sha256" == "$expected_sha256" ]] || fail "package SHA-256 did not match manifest"

actual_size="$(/usr/bin/stat -f%z "$package_path")"
[[ "$actual_size" == "$expected_size" ]] || fail "package size did not match manifest"

signature_info="$(/usr/sbin/pkgutil --check-signature "$package_path" 2>&1)" \
  || fail "package signature verification failed: $signature_info"
/usr/bin/grep -F "$INSTALLER_IDENTITY" <<<"$signature_info" >/dev/null \
  || fail "package was not signed by the expected Barndoor installer identity"
# spctl reports success on stderr; MDM consoles (Rippling) label any stderr
# as "Error", so capture it and surface it only on failure.
gatekeeper_info="$(/usr/sbin/spctl --assess --type install --verbose=4 "$package_path" 2>&1)" \
  || fail "package failed macOS Gatekeeper assessment: $gatekeeper_info"
/usr/sbin/installer -pkg "$package_path" -target /

installed_after="$(installed_version || true)"
[[ "$installed_after" == "$wanted_version" ]] || fail "installer completed but GUI reports ${installed_after:-no version}, expected $wanted_version"
echo "barndoor-mdm-update: installed $wanted_version ($CHANNEL channel)"
