#!/usr/bin/env bash
# Fail-closed seat process attestation for shell wrappers.
# Optional first argument: fixture proc-self root (tests only).

_overdeck_seat_id_safe() {
  local id="$1"
  [[ "$id" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]
}

_overdeck_seat_host_matches_local() {
  local seat_host="$1"
  local local_short local_full
  local_short=$(hostname -s)
  local_full=$(hostname)
  [ "$seat_host" = "$local_short" ] || [ "$seat_host" = "$local_full" ]
}

_overdeck_seat_attest() {
  local proc_root="${1:-}"
  local netns_override="${2:-}"
  local cgroup_file net_link seat_id seat_host scope netns_path
  seat_id="${OVERDECK_SEAT_ID:-}"
  seat_host="${OVERDECK_SEAT_HOST:-}"

  if [ -n "$proc_root" ]; then
    cgroup_file="$proc_root/cgroup"
    net_link="$proc_root/ns/net"
  else
    cgroup_file="/proc/self/cgroup"
    net_link="/proc/self/ns/net"
  fi

  if [ -z "$seat_id" ] || ! _overdeck_seat_id_safe "$seat_id"; then
    echo "seat-attest: invalid OVERDECK_SEAT_ID" >&2
    return 97
  fi
  if [ -z "$seat_host" ]; then
    echo "seat-attest: missing OVERDECK_SEAT_HOST" >&2
    return 97
  fi
  if ! _overdeck_seat_host_matches_local "$seat_host"; then
    echo "seat-attest: OVERDECK_SEAT_HOST mismatch ($seat_host)" >&2
    return 97
  fi

  scope="agent-seat-${seat_id}.scope"
  if ! grep -qF "$scope" "$cgroup_file" 2>/dev/null; then
    echo "seat-attest: scope cgroup mismatch (want $scope)" >&2
    return 97
  fi

  netns_path="${netns_override:-/var/run/netns/overdeck-seat-${seat_id}}"
  if [ ! -L "$netns_path" ] && [ ! -e "$netns_path" ]; then
    echo "seat-attest: netns path missing ($netns_path)" >&2
    return 97
  fi
  if [ "$(stat -c '%u' "$netns_path" 2>/dev/null || echo x)" != "0" ]; then
    echo "seat-attest: netns owner mismatch ($netns_path)" >&2
    return 97
  fi

  local self_inode want_inode
  self_inode=$(stat -L -c '%d:%i' "$net_link")
  want_inode=$(stat -L -c '%d:%i' "$netns_path")
  if [ "$self_inode" != "$want_inode" ]; then
    echo "seat-attest: netns inode mismatch" >&2
    return 97
  fi
  return 0
}

overdeck_seat_attest_or_die() {
  _overdeck_seat_attest "${1:-}" "${2:-}" || exit $?
}
