#!/bin/bash
# ============================================================================
# rq-historical — eng begrenzter root-Wrapper fuer Red Queen (rq-host)
# RED-QUEEN-VPS-HOST-ACCESS + PHASE-13.5-READONLY | Rain Ocampo (Hermes) | 2026-08-29
#
# EINZIGER ZWECK: kontrollierter READ-ONLY-Zugriff + freigegebener Backfill-
# Start ausschliesslich auf den Historical-Service. Least-Privilege.
#
# SICHERHEIT:
#   - Container-/Skript-Namen sind FEST im Script (kein Benutzer-Argument
#     fuer Container/Skript/Pfad).
#   - Alle Subkommandos akzeptieren NUR strikt validierte, vollstaendig
#     konsumierte Argumente; unbekannte/ueberzaehlige Argumente -> ERR.
#   - code/hashes/code-list nutzen eine FESTE Allowlist: User uebergibt nur
#     einen Key, der intern auf einen festen Containerpfad gemappt wird.
#     KEIN frei durchgereichter Pfad, KEIN Shell-String aus User-Input.
#   - Argumente werden als argv-Array an `docker exec` uebergeben
#     (KEINE Shell-Interpolation von Benutzereingaben).
#   - KEIN sudo ALL / NOPASSWD ALL / keine Root-Shell / kein docker run.
#
# AUFRUF (ueber /etc/sudoers.d/rq-historical, NUR als root):
#   sudo rq-historical ps
#   sudo rq-historical inspect
#   sudo rq-historical logs [--tail N]
#   sudo rq-historical run [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--limit-days N]
#   sudo rq-historical code <runner|backfill|pipeline|repository|provenance|trust|sanity|trust_gate>
#   sudo rq-historical hashes
#   sudo rq-historical code-list
# ============================================================================
set -euo pipefail

CONTAINER=historical-service

# ------------------------------------------------------------------ Allowlist
# FESTE Mapping-Tabelle (Key -> Containerpfad). Read-only, hart im Script.
# Keys NICHT benutzerdefiniert erweiterbar.
# NOTE: Bei assign-assoc-array die Assignments OHNE Leerzeichen um '=' schreiben,
# sonst Syntaxfehler. (Korrektur unten: einzeilig mit declare -A init.)
declare -A CODE_FILES=(
  [runner]="/app/app/run_backfill_year.py"
  [backfill]="/app/app/backfill.py"
  [pipeline]="/app/app/pipeline_v2.py"
  [repository]="/app/app/persistence/repository.py"
  [provenance]="/app/app/trust/provenance.py"
  [trust]="/app/app/trust/trust.py"
  [sanity]="/app/app/trust/sanity.py"
  [trust_gate]="/app/app/trust/trust_gate.py"
)

# Relevanter Pfad fuer den 'run'-Subbefehl (Backfill-Entrypoint)
SCRIPT=/app/app/run_backfill_year.py

# ---------------------------------------------------------------- Validierung
die()  { echo "ERR: $*" >&2; exit 2; }
req_ok() {
  docker inspect -f '{{.State.Running}}' "$CONTAINER" >/dev/null 2>&1 \
    || die "Container '$CONTAINER' nicht vorhanden oder nicht am Laufen"
}

# -------------------------------------------------------------------- dispatch
SUBCMD="${1:-}"
shift || true

case "$SUBCMD" in
  ps)
    [ $# -eq 0 ] || die "unerlaubtes Argument 'ps $*'"
    exec docker ps
    ;;
  inspect)
    req_ok
    [ $# -eq 0 ] || die "unerlaubtes Argument 'inspect $*'"
    exec docker inspect "$CONTAINER"
    ;;
  logs)
    req_ok
    tail_n=200
    while [ $# -gt 0 ]; do
      case "$1" in
        --tail)
          [ $# -ge 2 ] || die "--tail braucht Wert"
          [[ "$2" =~ ^[0-9]+$ ]] || die "ungueltiges --tail"
          tail_n="$2"; shift 2 ;;
        *) die "unerlaubtes Argument 'logs $1'" ;;
      esac
    done
    exec docker logs --tail "$tail_n" "$CONTAINER"
    ;;
  run)
    req_ok
    declare -a RUN=()
    while [ $# -gt 0 ]; do
      case "$1" in
        --start)      [[ "${2:-}" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || die "ungueltiges --start"; RUN+=("--start" "$2"); shift 2 ;;
        --end)        [[ "${2:-}" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || die "ungueltiges --end";   RUN+=("--end" "$2");   shift 2 ;;
        --limit-days) [[ "${2:-}" =~ ^[0-9]+$ ]]                       || die "ungueltiges --limit-days"; RUN+=("--limit-days" "$2"); shift 2 ;;
        *) die "unerlaubtes Argument 'run $1'" ;;
      esac
    done
    echo "[rq-historical] Start: docker exec $CONTAINER python $SCRIPT ${RUN[*]}" >&2
    exec docker exec "$CONTAINER" python "$SCRIPT" "${RUN[@]}"
    ;;
  code)
    # Fester Allowlist-Key -> fester Containerpfad. KEIN frei gereichter Pfad.
    req_ok
    [ $# -eq 1 ] || die "code braucht genau EINEN Key (siehe code-list)"
    key="$1"
    path="${CODE_FILES[$key]:-}"
    [ -n "$path" ] || die "unbekannter Key 'code $key' (siehe code-list)"
    exec docker exec "$CONTAINER" cat "$path"
    ;;
  hashes)
    # SHA256 der festen Allowlist-Dateien aus dem laufenden Container.
    req_ok
    [ $# -eq 0 ] || die "unerlaubtes Argument 'hashes $*'"
    # Feste, vollstaendig konsumierte Dateiliste -> argv-Array (keine Interpolation).
    declare -a PATHS=()
    for k in "${!CODE_FILES[@]}"; do PATHS+=("${CODE_FILES[$k]}"); done
    exec docker exec "$CONTAINER" sha256sum "${PATHS[@]}"
    ;;
  code-list)
    # Nur die verfuegbaren fixen Keys + Containerpfade anzeigen. Kein FS-Zugriff.
    req_ok
    [ $# -eq 0 ] || die "unerlaubtes Argument 'code-list $*'"
    echo "Verfuegbare READ-ONLY-Code-Keys (historical-service):"
    for k in "${!CODE_FILES[@]}"; do
      printf '  %-11s -> %s\n' "$k" "${CODE_FILES[$k]}"
    done
    ;;
  *)
    die "Aufruf: rq-historical {ps|inspect|logs [--tail N]|run [--start --end --limit-days]|code <KEY>|hashes|code-list}"
    ;;
esac
