#!/bin/bash
# PrivacyFence.pkg postinstall — provisions privilege separation (#428 D2,
# Phase 4) at install time. The .pkg is the only way PrivacyFence is installed
# on macOS (scripts/build_dmg.sh ships it, and nothing else that installs,
# inside the DMG), so this is where every install becomes separated: Apple's
# installer already verified this package's signature before running it and
# always runs package scripts as root, so by the time this runs, "provision
# the _privacyfence account and hand it the daemon" is exactly as safe to do
# unconditionally as scripts/macos_privilege_separation.sh enable --auto
# already assumes its caller has confirmed. It provisions the current layout
# only; there is nothing from an earlier install to move (ADR 0041).
#
# Must never fail the package install over this: a hiccup here is a reason to
# finish separating later, never a reason to roll back installing the app at
# all. The daemon's own startup does that later -- privilege_separation.
# maybe_auto_enable_macos(), an admin-password prompt, reached when something
# (the .mcpb's shim, say) starts the packaged daemon on an install this left
# unseparated. Every exit path below is therefore explicit and this script
# always exits 0 -- no `set -e`, so one unexpected failure can't accidentally
# take the whole install down with it.
set -uo pipefail

APP_PATH="/Applications/PrivacyFenceApp.app"
SEPARATION_SCRIPT="${APP_PATH}/Contents/Resources/scripts/macos_privilege_separation.sh"

log() { printf 'PrivacyFence postinstall: %s\n' "$*" >&2; }

# Apple's installer runs this as root with no login session of its own --
# $SUDO_USER (what macos_privilege_separation.sh normally reads) is unset here,
# whether this ran from the Installer.app GUI or `sudo installer -pkg ...`.
# The actual human to provision this for is whoever is logged in at the
# console, the same thing `who`/Finder would show -- stat on /dev/console is
# the standard, dependency-free way any macOS installer script resolves that.
CONSOLE_USER="$(/usr/bin/stat -f '%Su' /dev/console 2>/dev/null || true)"

if [ -z "$CONSOLE_USER" ] || [ "$CONSOLE_USER" = "root" ] || [ "$CONSOLE_USER" = "loginwindow" ]; then
  # Nobody is actually logged in at install time (a remote/unattended install,
  # or a package run at the login window) -- there is no human account yet to
  # add to the service group. That used to end this script, leaving the whole
  # install unseparated; ADR 0003 decision 3 splits `enable` so it no longer
  # has to. The machine half below runs regardless and fully separates the
  # install, and the one step that genuinely needs a human -- the group
  # membership -- is recorded as pending, which the companion app closes by
  # itself at the first real login session.
  log "no logged-in console user detected (got '${CONSOLE_USER:-<empty>}') -- provisioning the machine half and leaving the group membership pending."
  CONSOLE_USER=""
fi

if [ ! -x "$SEPARATION_SCRIPT" ]; then
  # Should not happen from a package this script itself ships inside of, but
  # never worth failing the install over; the daemon's own start retries it.
  log "${SEPARATION_SCRIPT} not found or not executable -- not provisioning privilege separation now."
  exit 0
fi

log "provisioning privilege separation for ${CONSOLE_USER:-this machine} (#428 D2, ADR 0003 decision 3)…"
ENABLE_STATUS=0
if [ -n "$CONSOLE_USER" ]; then
  "$SEPARATION_SCRIPT" enable --auto --user "$CONSOLE_USER" --app "$APP_PATH" || ENABLE_STATUS=$?
else
  "$SEPARATION_SCRIPT" enable --auto --app "$APP_PATH" || ENABLE_STATUS=$?
fi
if [ "$ENABLE_STATUS" -eq 0 ]; then
  if [ -n "$CONSOLE_USER" ]; then
    log "privilege separation enabled -- ${CONSOLE_USER} still needs to log out and back in once before the companion app and MCP client can reach the daemon (macOS only evaluates group membership at login; see 'sudo ${SEPARATION_SCRIPT} status')."
  else
    log "privilege separation enabled -- nobody is in the service group yet; the companion app adds the first account to log in, or run 'sudo ${SEPARATION_SCRIPT} enable --for-user <name>'."
  fi
else
  # enable --auto itself never exits non-zero (it logs and returns 0 on every
  # failure path -- see that script's own --auto handling), so reaching this
  # branch at all means the script couldn't even run to completion. Still not
  # a reason to fail the package install.
  log "automatic privilege-separation enable did not complete -- install continues; run 'sudo ${SEPARATION_SCRIPT} enable' by hand later, or check Console.app / /var/log/install.log for details."
fi

# #428 Phase 2: `enable`'s own internal call to `daemon ensure-running`
# (scripts/macos_privilege_separation.sh's cmd_enable) is what is *supposed*
# to catch a daemon that came up stopped -- the privacyfence/privacyfence#598
# upgrade gap this phase exists to close -- but that call is itself wrapped
# in a subshell precisely so a hiccup in it cannot take the rest of `enable`
# down, which also means its own failure is easy to miss in a log this long.
# Running `daemon ensure-running` a second time here, directly, costs
# nothing when the first call already succeeded (it is a no-op against an
# already-running daemon) and catches the case where it did not -- whether
# `enable --auto` above reported success or not: ENABLE_STATUS above is
# about `enable` completing, not about the daemon specifically ending up
# running, and #598 was exactly a case where the two came apart.
ENSURE_RUNNING_OUTPUT="$("$SEPARATION_SCRIPT" daemon ensure-running 2>&1)"
ENSURE_RUNNING_STATUS=$?
if [ "$ENSURE_RUNNING_STATUS" -eq 0 ]; then
  log "confirmed the daemon is running after install."
else
  # Still not a reason to fail the package install -- see this script's own
  # header. The companion app's tray menu (#428 Phase 2 §2.5) now surfaces a
  # stopped daemon with a Start button, so a failed start here is no longer
  # silent the way it used to be before this phase.
  log "could not confirm the daemon is running after install: ${ENSURE_RUNNING_OUTPUT}"
fi

exit 0
