#!/bin/bash
# git-credential-mosaic — git credential helper — resolves Gitea tokens from
# the Mosaic credential store at runtime so remote URLs never embed secrets.
#
# Install (one-time, per clone or globally):
#   git config credential.helper "$HOME/.config/mosaic/tools/git/git-credential-mosaic"
#   # or, fleet-wide: git config --global credential.helper "$HOME/.config/mosaic/tools/git/git-credential-mosaic"
#
# Per-agent Gate-16 identity (author != reviewer separation):
#   git config mosaic.gitIdentity <agent-id>   # per-worktree, persists on disk
#   # or: export MOSAIC_GIT_IDENTITY=<agent-id>
#
# Resolution priority: MOSAIC_GIT_IDENTITY env > git config mosaic.gitIdentity
# (per-worktree, survives across non-persistent shells) > git-supplied username
# (credential.username / URL). When the resolved identity has a matching
# per-agent token file, use it instead of the shared account. Backward
# compatible: nothing resolvable -> shared token (unchanged behavior).
[ "$1" = "get" ] || exit 0
host=""; username_in=""
while IFS= read -r line; do
  [ -z "$line" ] && break
  case "$line" in
    host=*)     host=${line#host=};;
    username=*) username_in=${line#username=};;
  esac
done
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
trace_resolution() {
  [ "${MOSAIC_CREDENTIAL_TRACE:-}" = 1 ] || return 0
  resolution_path="$1" reason="$2" trace_identity="$3" trace_host="$4" source="$5"
  shared_path_entered=false
  [ "$resolution_path" = shared ] && shared_path_entered=true
  printf 'MOSAIC_CREDENTIAL_RESOLUTION outcome=ok reason=%s identity=%s host=%s resolution_path=%s shared_path_entered=%s source=%s\n' \
    "$reason" "$trace_identity" "$trace_host" "$resolution_path" "$shared_path_entered" "$source" >&2
}
# Per-agent identity resolution (Gate-16 author≠reviewer separation).
# Priority: MOSAIC_GIT_IDENTITY env  >  git config mosaic.gitIdentity (per-worktree,
# survives across non-persistent shells)  >  git-supplied username (credential.username
# / URL). When the resolved identity has a matching per-agent token, use it instead of
# the shared account. Backward-compatible: nothing resolvable → shared token.
ident="$MOSAIC_GIT_IDENTITY"
[ -z "$ident" ] && ident=$(git config --get mosaic.gitIdentity 2>/dev/null)
[ -z "$ident" ] && ident="$username_in"
if [ -n "${MOSAIC_AGENT_NAME:-}" ] && [ -n "$ident" ] && [ "$ident" != "$MOSAIC_AGENT_NAME" ]; then
  echo "quit=true"
  printf 'MOSAIC_CREDENTIAL_REFUSAL outcome=refused reason=provider-identity-mismatch identity=%s fleet_identity=%s host=%s shared_path_entered=false source=git-credential-mosaic\n' \
    "$ident" "$MOSAIC_AGENT_NAME" "$host" >&2
  exit 1
fi
if [ -n "$ident" ]; then
  case "$host" in
    git.uscllc.com)      idpfx=gitea-usc;;
    git.mosaicstack.dev) idpfx=gitea-mosaicstack;;
    *) idpfx="";;
  esac
  if [ -n "$idpfx" ]; then
    idtok="$HOME/.config/mosaic/secrets/gitea-tokens/${idpfx}-${ident}.token"
    idcred="$HOME/.config/mosaic/secrets/gitea-tokens/${idpfx}-${ident}.credential.json"
    if [ -r "$idcred" ]; then
      token=$(python3 "$script_dir/resolve-credential-envelope.py" \
        "$idcred" "$ident" "${MOSAIC_CREDENTIAL_ESTATE:-}" "$host") || exit 1
      trace_resolution identity credential-resolved "$ident" "$host" git-credential-mosaic
      echo "username=${ident}"
      echo "password=${token}"
      exit 0
    fi
    if [ -r "$idtok" ]; then
      trace_resolution identity credential-resolved "$ident" "$host" git-credential-mosaic
      echo "username=${ident}"
      echo "password=$(cat "$idtok")"
      exit 0
    fi
    if [ -n "${MOSAIC_AGENT_NAME:-}" ]; then
      echo "quit=true"
      printf 'MOSAIC_CREDENTIAL_REFUSAL outcome=refused reason=no-token-for-identity identity=%s host=%s shared_path_entered=false source=git-credential-mosaic path=%s\n' \
        "$ident" "$host" "$idtok" >&2
      exit 1
    fi
  fi
fi
if [ -n "${MOSAIC_AGENT_NAME:-}" ] && [ -z "$ident" ]; then
  case "$host" in
    git.uscllc.com|git.mosaicstack.dev)
      echo "quit=true"
      printf 'MOSAIC_CREDENTIAL_REFUSAL outcome=refused reason=identity-required identity=<unset> host=%s shared_path_entered=false source=git-credential-mosaic\n' "$host" >&2
      exit 1
      ;;
  esac
fi
case "$host" in
  git.uscllc.com)      svc=gitea-usc;;
  git.mosaicstack.dev) svc=gitea-mosaicstack;;
  *) exit 0;;
esac
# Script-relative (not $HOME-absolute) so this resolves correctly regardless
# of where the framework installer places tools/ under $HOME — mirrors
# detect-platform.sh's own cred_loader resolution in this same directory.
# shellcheck source=../_lib/credentials.sh
source "$script_dir/../_lib/credentials.sh"
load_credentials "$svc" >/dev/null 2>&1 || exit 0
trace_resolution shared shared-credential-resolved '<interactive-shared>' "$host" credentials-loader
# GITEA_USER is not populated by load_credentials (it only exports
# GITEA_URL/GITEA_TOKEN for gitea-*), so this fallback is normally taken. Gitea's
# git-over-HTTP auth authenticates from the token itself (the password field),
# not from the username string, so any non-empty placeholder works here — this
# is deliberately NOT a real account name (framework files must stay
# operator-agnostic; see tools/quality/scripts/verify-sanitized.sh).
echo "username=${GITEA_USER:-git}"
echo "password=$GITEA_TOKEN"
