#!/usr/bin/bash
# install-seat-guard — block-only cgroup-checked PATH wrappers for claude, claudex, claude-code-proxy.
# Operator binaries are never moved, shadowed, or recorded.
set -uo pipefail

MARKER="overdeck-seat-guard v3"
STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
GUARD_ROOT="${STATE_HOME}/overdeck/seat-guard"
LIVE_ROOT="${HOME}/.local/share/overdeck/seat-guard"
RELEASES="${GUARD_ROOT}/releases"
CURRENT="${GUARD_ROOT}/current"
WRAPPER_NAMES="claude claudex claude-code-proxy"

usage() {
  cat >&2 <<'USAGE'
usage: install-seat-guard [--uninstall] [--status]

Publish block-only cgroup-checked wrappers under
~/.local/state/overdeck/seat-guard/releases/<release-id>/bin, atomically repoint
its current release, and expose the legacy runtime path as a symlink to state.
USAGE
  exit "${1:-2}"
}

write_wrapper() {
  local dest=$1 name=$2
  cat >"$dest" <<GUARD
#!/usr/bin/bash
# $MARKER — DO NOT EDIT. Reinstall with ~/.claude/bin/install-seat-guard
if grep -qE '(^|/)agent-seat-[^/]+\\.scope' /proc/self/cgroup 2>/dev/null; then
  cat >&2 <<'MSG'
BLOCKED: $name may not run inside an agent seat scope.

Use the seat launcher for nested Claude/claudex/proxy work inside seats.
MSG
  exit 97
fi
echo "seat-guard: $name wrapper is block-only; operator PATH must not prepend guard bin" >&2
exit 126
GUARD
  chmod 755 "$dest"
}

release_id() {
  printf '%s-%s' "$(date -u +%Y%m%dT%H%M%SZ)" "$$"
}

install_release() {
  mkdir -p "$RELEASES" "$(dirname "$LIVE_ROOT")" || return 1
  if [ -e "$LIVE_ROOT" ] && [ ! -L "$LIVE_ROOT" ]; then
    echo "install-seat-guard: refusing to replace non-symlink $LIVE_ROOT" >&2
    return 1
  fi
  ln -sfn "$GUARD_ROOT" "${LIVE_ROOT}.tmp.$$" || return 1
  mv -Tf "${LIVE_ROOT}.tmp.$$" "$LIVE_ROOT" || { rm -f "${LIVE_ROOT}.tmp.$$"; return 1; }
  local rid bin_dir staging
  rid=$(release_id) || return 1
  bin_dir="$RELEASES/$rid/bin"
  staging=$(mktemp -d "${GUARD_ROOT}/staging.XXXXXX") || return 1
  mkdir -p "$staging/bin" || { rm -rf "$staging"; return 1; }
  for name in $WRAPPER_NAMES; do
    write_wrapper "$staging/bin/$name" "$name" || { rm -rf "$staging"; return 1; }
  done
  mkdir -p "$bin_dir" || { rm -rf "$staging"; return 1; }
  for name in $WRAPPER_NAMES; do
    mv -f -- "$staging/bin/$name" "$bin_dir/$name" || { rm -rf "$staging"; return 1; }
  done
  rm -rf "$staging"
  ln -sfn "releases/$rid" "${CURRENT}.tmp.$$" || return 1
  mv -Tf "${CURRENT}.tmp.$$" "$CURRENT" || { rm -f "${CURRENT}.tmp.$$"; return 1; }
  printf '%s\n' "$rid"
}

uninstall_wrappers() {
  rm -f -- "$LIVE_ROOT"
  rm -f -- "$CURRENT"
  rm -rf -- "$RELEASES"
  rmdir -- "$GUARD_ROOT" 2>/dev/null || true
}

wrapper_block_only() {
  local wrapper=$1
  grep -qF "$MARKER" "$wrapper" 2>/dev/null || return 1
  grep -qE '(^|[[:space:]])exec[[:space:]]' "$wrapper" && return 1
  grep -qF 'targets.json' "$wrapper" && return 1
  grep -qF 'exit 97' "$wrapper" || return 1
  return 0
}

check_status() {
  local missing=0 stale=0 rid current_target bin_dir
  if [ ! -L "$CURRENT" ]; then
    echo "MISSING $CURRENT symlink" >&2
    missing=$((missing + 1))
  else
    current_target=$(readlink "$CURRENT" 2>/dev/null || true)
  fi
  if [ -z "${current_target:-}" ]; then
    echo "STALE $CURRENT unreadable" >&2
    stale=$((stale + 1))
  else
  case "$current_target" in
    ../*|/*)
      echo "STALE $CURRENT target escapes guard root: $current_target" >&2
      stale=$((stale + 1))
      ;;
    releases/*)
      bin_dir="$GUARD_ROOT/$current_target/bin"
      [ -d "$bin_dir" ] || { echo "STALE release missing: $bin_dir" >&2; stale=$((stale + 1)); }
      ;;
    *)
      echo "STALE $CURRENT target not under releases/: $current_target" >&2
      stale=$((stale + 1))
      ;;
  esac
  fi
  for name in $WRAPPER_NAMES; do
    local wrapper="${bin_dir:-$CURRENT/bin}/$name"
    if [ ! -f "$wrapper" ] || [ ! -x "$wrapper" ]; then
      echo "MISSING $wrapper" >&2
      missing=$((missing + 1))
      continue
    fi
    if ! wrapper_block_only "$wrapper"; then
      echo "STALE $wrapper not block-only" >&2
      stale=$((stale + 1))
      continue
    fi
    local mode
    mode=$(stat -c '%a' "$wrapper" 2>/dev/null || echo "")
    [ "$mode" = "755" ] || { echo "STALE $wrapper mode=$mode" >&2; stale=$((stale + 1)); }
  done
  if ! grep -rqF "$MARKER" "${bin_dir:-$CURRENT/bin}" 2>/dev/null; then
    echo "MISSING seat-guard marker under ${bin_dir:-$CURRENT/bin}" >&2
    missing=$((missing + 1))
  fi
  echo "install-seat-guard: missing=$missing stale=$stale current=${CURRENT}${rid:+ release=$rid}"
  [ "$missing" -eq 0 ] && [ "$stale" -eq 0 ] || exit 1
}

MODE=install
while [ $# -gt 0 ]; do
  case "$1" in
    --uninstall) MODE=uninstall; shift ;;
    --status) MODE=status; shift ;;
    -h|--help) usage 0 ;;
    *) echo "install-seat-guard: unknown arg: $1" >&2; usage ;;
  esac
done

case "$MODE" in
  install)
    rid=$(install_release) || exit 1
    echo "install-seat-guard: published release $rid ($CURRENT/bin)" ;;
  uninstall)
    uninstall_wrappers
    echo "install-seat-guard: removed ($GUARD_ROOT)" ;;
  status)
    check_status ;;
esac
