#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

STEP="STEP_050M07R07_REVIEW_REFRESH_POOL_SAFE_AND_BUILD_BUNDLE"

TOKEN="e94a0859747d7b96f29c7fdafc2d0351ba603bb0a7e9e5a4"
ROOT="/opt/router-ops"
STATE="$ROOT/state"
PUBROOT="$ROOT/public/r/$TOKEN"
PUBLIC_BASE="https://helena-background-beam-harry.trycloudflare.com/r/$TOKEN"

WORKFLOW_STATE="$STATE/current-m07-workflow.env"
CANONICAL_STATE="$STATE/current-vm101-canonical.env"

TS="$(date -u +%Y%m%d-%H%M%S)"

BUNDLE_ROOT="$STATE/m07-install-bundles/refresh_pool_safe"
BUNDLE="$BUNDLE_ROOT/${TS}_refresh_pool_safe_r06b"
ARCHIVE="${BUNDLE}.tar.gz"

REPORT_SLUG="${TS}_step050m07r07_review_refresh_pool_safe_and_build_bundle"
REPORT_DIR="$PUBROOT/$REPORT_SLUG"

TRYCF_REPORT="$PUBLIC_BASE/$REPORT_SLUG/"
REPORT_TXT="${TRYCF_REPORT}report.txt"
FACTS_JSON="${TRYCF_REPORT}facts.json"

VM101_REFERENCE="$PUBLIC_BASE/vm101-reference/current/"
VM101_CANONICAL="$PUBLIC_BASE/vm101-canonical/current/"

SOURCE_WORKSPACE="UNRESOLVED"
CANONICAL_WORKSPACE="UNRESOLVED"

SOURCE_FILE="UNRESOLVED"
CANDIDATE_FILE="UNRESOLVED"
RUNTIME_FILE="UNRESOLVED"

EXPECTED_SOURCE_SHA="UNRESOLVED"
EXPECTED_CANDIDATE_SHA="UNRESOLVED"

SOURCE_SHA="UNRESOLVED"
CANDIDATE_SHA="UNRESOLVED"
RUNTIME_SHA="UNRESOLVED"
ARCHIVE_SHA="UNRESOLVED"

DIFF_REVIEW_PASS=false
SYNTAX_PASS=false
BUNDLE_PASS=false
ALL_OK=false

VM101_CONTACTED=false
VM101_MODIFIED=false
CANONICAL_CURRENT_MODIFIED=false
INSTALLATION_PERFORMED=false

mkdir -p "$REPORT_DIR" "$BUNDLE_ROOT"
cp -a "$0" "$REPORT_DIR/step.sh"
chmod 600 "$REPORT_DIR/step.sh"

value() {
  local file="$1"
  local key="$2"

  sed -n "s/^${key}=//p" "$file" |
    tail -n1
}

publish_report() {
  local execution="$1"
  local operation="$2"
  local reason="$3"

  python3 - \
    "$REPORT_DIR/facts.json" \
    "$STEP" \
    "$execution" \
    "$operation" \
    "$reason" \
    "$SOURCE_WORKSPACE" \
    "$BUNDLE" \
    "$ARCHIVE" \
    "$SOURCE_SHA" \
    "$CANDIDATE_SHA" \
    "$RUNTIME_SHA" \
    "$ARCHIVE_SHA" \
    "$DIFF_REVIEW_PASS" \
    "$SYNTAX_PASS" \
    "$BUNDLE_PASS" \
    "$ALL_OK" \
    "$TRYCF_REPORT" \
    "$REPORT_TXT" \
    "$FACTS_JSON" <<'PY'
import json
import sys
from pathlib import Path

(
    output,
    step,
    execution,
    operation,
    reason,
    source_workspace,
    bundle,
    archive,
    source_sha,
    candidate_sha,
    runtime_sha,
    archive_sha,
    diff_pass,
    syntax_pass,
    bundle_pass,
    all_ok,
    report,
    report_txt,
    facts,
) = sys.argv[1:]

passed = execution == "PASS"

data = {
    "schema": "router-step-facts-v1",
    "step": step,
    "assessment": {
        "decision": (
            f"PASS_{step}"
            if passed
            else f"STOP_{step}_{reason}"
        ),
        "step_execution": execution,
        "operation_result": operation,
        "production_health": "UNCHANGED",
        "milestone_status": "M07_IN_PROGRESS",
        "all_ok": all_ok == "true",
        "failure_reason": None if passed else reason,
    },
    "source": {
        "private_workspace": source_workspace,
        "source_sha256": source_sha,
        "candidate_sha256": candidate_sha,
        "runtime_library_sha256": runtime_sha,
    },
    "review": {
        "private_diff_review_passed":
            diff_pass == "true",
        "syntax_passed":
            syntax_pass == "true",
    },
    "install_bundle": {
        "path": bundle,
        "archive": archive,
        "archive_sha256": archive_sha,
        "built": bundle_pass == "true",
        "installation_allowed_by_bundle":
            bundle_pass == "true",
        "installation_performed": False,
    },
    "safety": {
        "single_target": True,
        "local_only": True,
        "vm101_contacted": False,
        "vm101_modified": False,
        "canonical_current_modified": False,
        "installation_performed": False,
        "refresh_ran": False,
        "rebalance_ran": False,
    },
    "next_step": (
        "VM101_READ_ONLY_INSTALL_PREFLIGHT"
        if passed
        else "FIX_REFRESH_POOL_SAFE_DIFF_OR_BUNDLE"
    ),
    "publish": {
        "trycf_report": report,
        "report_txt": report_txt,
        "facts_json": facts,
    },
}

Path(output).write_text(
    json.dumps(
        data,
        ensure_ascii=False,
        indent=2,
    ) + "\n",
    encoding="utf-8",
)
PY

  cat > "$REPORT_DIR/report.txt" <<EOF
=== ${STEP} RESULT ===
step=${STEP}
decision=$(
  if [ "$execution" = "PASS" ]; then
    echo "PASS_${STEP}"
  else
    echo "STOP_${STEP}_${reason}"
  fi
)
step_execution=${execution}
operation_result=${operation}
production_health=UNCHANGED
milestone_status=M07_IN_PROGRESS
all_ok=${ALL_OK}

source:
  workspace=${SOURCE_WORKSPACE}
  source_sha256=${SOURCE_SHA}
  candidate_sha256=${CANDIDATE_SHA}
  runtime_library_sha256=${RUNTIME_SHA}

review:
  private_diff_review_passed=${DIFF_REVIEW_PASS}
  syntax_passed=${SYNTAX_PASS}

install_bundle:
  path=${BUNDLE}
  archive=${ARCHIVE}
  archive_sha256=${ARCHIVE_SHA}
  built=${BUNDLE_PASS}
  installation_performed=false

safety:
  single_target=true
  local_only=true
  vm101_contacted=false
  vm101_modified=false
  canonical_current_modified=false
  installation_performed=false
  refresh_ran=false
  rebalance_ran=false

failure_reason=${reason}

next_step=$(
  if [ "$execution" = "PASS" ]; then
    echo "VM101_READ_ONLY_INSTALL_PREFLIGHT"
  else
    echo "FIX_REFRESH_POOL_SAFE_DIFF_OR_BUNDLE"
  fi
)

TRYCF_REPORT=${TRYCF_REPORT}
REPORT_TXT=${REPORT_TXT}
FACTS_JSON=${FACTS_JSON}
VM101_REFERENCE=${VM101_REFERENCE}
VM101_CANONICAL=${VM101_CANONICAL}
EOF

  cat > "$REPORT_DIR/index.html" <<EOF
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>${STEP}</title>
</head>
<body style="font-family:system-ui;max-width:1000px;margin:40px auto">
<h1>${STEP}</h1>
<ul>
<li><a href="report.txt">report.txt</a></li>
<li><a href="facts.json">facts.json</a></li>
<li><a href="diff-review.json">diff-review.json</a></li>
<li><a href="bundle-manifest-public.json">bundle-manifest-public.json</a></li>
<li><a href="syntax-checks.txt">syntax-checks.txt</a></li>
<li><a href="step.sh">step.sh</a></li>
</ul>
<p>Payload, полный diff и install bundle остаются приватными на VM130.</p>
</body>
</html>
EOF

  find "$REPORT_DIR" \
    -type f \
    ! -name SHA256SUMS \
    -print0 |
    sort -z |
    xargs -0 sha256sum \
    > "$REPORT_DIR/SHA256SUMS"

  chmod -R a+rX "$REPORT_DIR"

  echo
  echo "TRYCF_REPORT=$TRYCF_REPORT"
  echo "REPORT_TXT=$REPORT_TXT"
  echo "FACTS_JSON=$FACTS_JSON"
  echo "VM101_REFERENCE=$VM101_REFERENCE"
  echo "VM101_CANONICAL=$VM101_CANONICAL"
}

stop_step() {
  local reason="$1"

  ALL_OK=false

  publish_report \
    "STOP" \
    "REFRESH_POOL_SAFE_INSTALL_BUNDLE_NOT_READY" \
    "$reason"

  exit 1
}

[ "$(id -un)" = "ops" ] ||
  stop_step "WRONG_USER"

[ -s "$WORKFLOW_STATE" ] ||
  stop_step "WORKFLOW_STATE_MISSING"

[ -s "$CANONICAL_STATE" ] ||
  stop_step "CANONICAL_STATE_MISSING"

SOURCE_WORKSPACE="$(
  value \
    "$WORKFLOW_STATE" \
    M07_REFRESH_POOL_SAFE_WORKSPACE
)"

EXPECTED_SOURCE_SHA="$(
  value \
    "$WORKFLOW_STATE" \
    M07_REFRESH_POOL_SAFE_SOURCE_SHA256
)"

EXPECTED_CANDIDATE_SHA="$(
  value \
    "$WORKFLOW_STATE" \
    M07_REFRESH_POOL_SAFE_CANDIDATE_SHA256
)"

CANDIDATE_STATUS="$(
  value \
    "$WORKFLOW_STATE" \
    M07_REFRESH_POOL_SAFE_STATUS
)"

CANONICAL_WORKSPACE="$(
  value \
    "$CANONICAL_STATE" \
    VM101_CANONICAL_PRIVATE_WORKSPACE
)"

[ "$CANDIDATE_STATUS" = "CANDIDATE_TESTED_NOT_INSTALLED" ] ||
  stop_step "CANDIDATE_STATUS_INVALID"

[ -d "$SOURCE_WORKSPACE" ] ||
  stop_step "SOURCE_WORKSPACE_MISSING"

[ -d "$CANONICAL_WORKSPACE" ] ||
  stop_step "CANONICAL_WORKSPACE_MISSING"

SOURCE_FILE="$SOURCE_WORKSPACE/source/root/hmn/hmn-refresh-pool-safe.sh"
CANDIDATE_FILE="$SOURCE_WORKSPACE/candidate/root/hmn/hmn-refresh-pool-safe.sh"
RUNTIME_FILE="$CANONICAL_WORKSPACE/candidate/usr/local/lib/router-egress-vm101-runtime.sh"

for file in \
  "$SOURCE_FILE" \
  "$CANDIDATE_FILE" \
  "$RUNTIME_FILE"
do
  [ -s "$file" ] || {
    echo "MISSING=$file"
    stop_step "REQUIRED_FILE_MISSING"
  }
done

SOURCE_SHA="$(
  sha256sum "$SOURCE_FILE" |
    cut -d' ' -f1
)"

CANDIDATE_SHA="$(
  sha256sum "$CANDIDATE_FILE" |
    cut -d' ' -f1
)"

RUNTIME_SHA="$(
  sha256sum "$RUNTIME_FILE" |
    cut -d' ' -f1
)"

[ "$SOURCE_SHA" = "$EXPECTED_SOURCE_SHA" ] ||
  stop_step "SOURCE_SHA_MISMATCH"

[ "$CANDIDATE_SHA" = "$EXPECTED_CANDIDATE_SHA" ] ||
  stop_step "CANDIDATE_SHA_MISMATCH"

: > "$REPORT_DIR/syntax-checks.txt"

if sh -n "$CANDIDATE_FILE"; then
  echo "PASS hmn-refresh-pool-safe.sh" \
    >> "$REPORT_DIR/syntax-checks.txt"
else
  stop_step "TARGET_SYNTAX_FAILED"
fi

if sh -n "$RUNTIME_FILE"; then
  echo "PASS router-egress-vm101-runtime.sh" \
    >> "$REPORT_DIR/syntax-checks.txt"
else
  stop_step "RUNTIME_LIBRARY_SYNTAX_FAILED"
fi

SYNTAX_PASS=true

PRIVATE_DIFF="$SOURCE_WORKSPACE/diffs/refresh_pool_safe.private.diff"

diff -u \
  "$SOURCE_FILE" \
  "$CANDIDATE_FILE" \
  > "$PRIVATE_DIFF" ||
DIFF_RC=$?

DIFF_RC="${DIFF_RC:-0}"

[ "$DIFF_RC" -eq 1 ] ||
  stop_step "PRIVATE_DIFF_FAILED"

python3 - \
  "$SOURCE_FILE" \
  "$CANDIDATE_FILE" \
  "$PRIVATE_DIFF" \
  "$REPORT_DIR/diff-review.json" <<'PY'
import json
import re
import sys
from pathlib import Path

source_path = Path(sys.argv[1])
candidate_path = Path(sys.argv[2])
diff_path = Path(sys.argv[3])
output_path = Path(sys.argv[4])

source = source_path.read_text(
    encoding="utf-8",
    errors="strict",
)

candidate = candidate_path.read_text(
    encoding="utf-8",
    errors="strict",
)

diff_lines = diff_path.read_text(
    encoding="utf-8",
    errors="strict",
).splitlines()

function_pattern = re.compile(
    r"(?m)^[ \t]*"
    r"([A-Za-z_][A-Za-z0-9_]*)"
    r"[ \t]*\(\)[ \t]*\{"
)

source_functions = set(
    function_pattern.findall(source)
)

candidate_functions = set(
    function_pattern.findall(candidate)
)

removed = [
    line[1:]
    for line in diff_lines
    if line.startswith("-")
    and not line.startswith("---")
]

added = [
    line[1:]
    for line in diff_lines
    if line.startswith("+")
    and not line.startswith("+++")
]

allowed_removed = []

unexpected_removed = []

for line in removed:
    stripped = line.strip()

    allowed = (
        stripped == 'BACKUPDIR="$BASE/backups"'
        or (
            "$DOWNLOADER" in stripped
            and not stripped.startswith(
                "DOWNLOADER="
            )
        )
    )

    if allowed:
        allowed_removed.append(line)
    else:
        unexpected_removed.append(line)

required_added_functions = {
    "canonical_backup_dir",
    "canonical_verify_backup_manifest",
    "canonical_prepare_backup_manifest",
    "canonical_download_all_awg",
}

checks = {
    "all_original_functions_preserved":
        source_functions.issubset(
            candidate_functions
        ),

    "required_helper_functions_added":
        required_added_functions.issubset(
            candidate_functions
        ),

    "no_unexpected_removed_lines":
        not unexpected_removed,

    "expected_removed_line_count":
        len(removed) == 2,

    "runtime_library_loader_present":
        'VM101_RUNTIME_LIB=' in candidate
        and '. "$VM101_RUNTIME_LIB"'
        in candidate,

    "backup_root_redirected":
        'BACKUPDIR="$CANONICAL_BACKUP_ROOT"'
        in candidate
        and 'BACKUPDIR="$BASE/backups"'
        not in candidate,

    "original_downloader_preserved":
        'DOWNLOADER_ORIGINAL="$DOWNLOADER"'
        in candidate
        and '"$DOWNLOADER_ORIGINAL" "$@"'
        in candidate,

    "operational_download_wrapped":
        "canonical_download_all_awg"
        in candidate,

    "root_storage_preflight":
        "vm101_require_free_kb / 4096"
        in candidate,

    "tmp_storage_preflight":
        "vm101_require_free_kb /tmp 32768"
        in candidate,

    "backup_manifest_gate":
        "canonical_prepare_backup_manifest"
        in candidate
        and "canonical_verify_backup_manifest"
        in candidate
        and "manifest.complete" in candidate,

    "rollback_refusal_present":
        "rollback refused; backup manifest incomplete"
        in candidate,
}

failures = [
    name
    for name, passed in checks.items()
    if not passed
]

result = {
    "schema":
        "vm101-refresh-pool-safe-private-diff-review-v1",

    "passed": not failures,

    "source_function_count":
        len(source_functions),

    "candidate_function_count":
        len(candidate_functions),

    "added_functions":
        sorted(
            candidate_functions - source_functions
        ),

    "removed_function_names":
        sorted(
            source_functions - candidate_functions
        ),

    "diff": {
        "added_line_count": len(added),
        "removed_line_count": len(removed),
        "allowed_removed_lines":
            allowed_removed,
        "unexpected_removed_lines":
            unexpected_removed,
    },

    "checks": checks,
    "failures": failures,
}

output_path.write_text(
    json.dumps(
        result,
        ensure_ascii=False,
        indent=2,
    ) + "\n",
    encoding="utf-8",
)

if failures:
    raise SystemExit(20)
PY

DIFF_REVIEW_PASS=true

rm -rf "$BUNDLE"

mkdir -p \
  "$BUNDLE/payload/root/hmn" \
  "$BUNDLE/payload/usr/local/lib"

cp -a \
  "$CANDIDATE_FILE" \
  "$BUNDLE/payload/root/hmn/hmn-refresh-pool-safe.sh"

cp -a \
  "$RUNTIME_FILE" \
  "$BUNDLE/payload/usr/local/lib/router-egress-vm101-runtime.sh"

chmod 700 \
  "$BUNDLE/payload/root/hmn/hmn-refresh-pool-safe.sh"

chmod 644 \
  "$BUNDLE/payload/usr/local/lib/router-egress-vm101-runtime.sh"

cat > "$BUNDLE/manifest.tsv" <<EOF
destination	expected_before_sha256	candidate_sha256	mode
/root/hmn/hmn-refresh-pool-safe.sh	${SOURCE_SHA}	${CANDIDATE_SHA}	0700
/usr/local/lib/router-egress-vm101-runtime.sh	ABSENT_OR_EXACT	${RUNTIME_SHA}	0644
EOF

cat > "$BUNDLE/install.sh" <<EOF
#!/bin/sh
set -u

TARGET="/root/hmn/hmn-refresh-pool-safe.sh"
LIB="/usr/local/lib/router-egress-vm101-runtime.sh"

EXPECTED_TARGET_BEFORE="${SOURCE_SHA}"
EXPECTED_TARGET_AFTER="${CANDIDATE_SHA}"
EXPECTED_LIB_AFTER="${RUNTIME_SHA}"

SELF_DIR="\$(CDPATH= cd "\$(dirname "\$0")" && pwd)"

TARGET_SRC="\$SELF_DIR/payload/root/hmn/hmn-refresh-pool-safe.sh"
LIB_SRC="\$SELF_DIR/payload/usr/local/lib/router-egress-vm101-runtime.sh"

die() {
  echo "INSTALL_STOP=\$1" >&2
  exit 1
}

hash_file() {
  if command -v sha256sum >/dev/null 2>&1
  then
    sha256sum "\$1" |
      awk '{print \$1}'
  else
    busybox sha256sum "\$1" |
      awk '{print \$1}'
  fi
}

[ "\$(id -u)" -eq 0 ] ||
  die "ROOT_REQUIRED"

[ "\$#" -eq 2 ] ||
  die "USE: install.sh --apply CONFIRM_REFRESH_POOL_SAFE_R06B"

[ "\$1" = "--apply" ] ||
  die "APPLY_FLAG_REQUIRED"

[ "\$2" = "CONFIRM_REFRESH_POOL_SAFE_R06B" ] ||
  die "CONFIRMATION_INVALID"

[ -s "\$TARGET" ] ||
  die "LIVE_TARGET_MISSING"

[ -s "\$TARGET_SRC" ] ||
  die "BUNDLE_TARGET_MISSING"

[ -s "\$LIB_SRC" ] ||
  die "BUNDLE_LIBRARY_MISSING"

LIVE_TARGET_HASH="\$(hash_file "\$TARGET")" ||
  die "LIVE_TARGET_HASH_FAILED"

[ "\$LIVE_TARGET_HASH" = "\$EXPECTED_TARGET_BEFORE" ] ||
  die "LIVE_TARGET_HASH_MISMATCH:\$LIVE_TARGET_HASH"

[ "\$(hash_file "\$TARGET_SRC")" = "\$EXPECTED_TARGET_AFTER" ] ||
  die "BUNDLE_TARGET_HASH_MISMATCH"

[ "\$(hash_file "\$LIB_SRC")" = "\$EXPECTED_LIB_AFTER" ] ||
  die "BUNDLE_LIBRARY_HASH_MISMATCH"

if [ -e "\$LIB" ]
then
  LIVE_LIB_HASH="\$(hash_file "\$LIB")" ||
    die "LIVE_LIBRARY_HASH_FAILED"

  [ "\$LIVE_LIB_HASH" = "\$EXPECTED_LIB_AFTER" ] ||
    die "LIVE_LIBRARY_UNKNOWN_HASH:\$LIVE_LIB_HASH"

  LIB_EXISTED=true
else
  LIB_EXISTED=false
fi

ROOT_FREE_KB="\$(
  df -k / |
    awk 'NR == 2 {print \$4}'
)"

case "\$ROOT_FREE_KB" in
  ''|*[!0-9]*)
    die "ROOT_FREE_SPACE_UNRESOLVED"
    ;;
esac

[ "\$ROOT_FREE_KB" -ge 1024 ] ||
  die "ROOT_FREE_SPACE_LOW:\$ROOT_FREE_KB"

STAMP="\$(
  date -u +%Y%m%d-%H%M%S 2>/dev/null ||
  date +%Y%m%d-%H%M%S
)"

BACKUP="/root/hmn/backups/m07-refresh-pool-safe-install-\${STAMP}-\$\$"

mkdir -p "\$BACKUP" ||
  die "BACKUP_CREATE_FAILED"

cp -p "\$TARGET" "\$BACKUP/hmn-refresh-pool-safe.sh.before" ||
  die "TARGET_BACKUP_FAILED"

if [ "\$LIB_EXISTED" = "true" ]
then
  cp -p "\$LIB" "\$BACKUP/router-egress-vm101-runtime.sh.before" ||
    die "LIBRARY_BACKUP_FAILED"
fi

printf '%s\n' \
  "target_before_sha256=\$LIVE_TARGET_HASH" \
  "library_existed=\$LIB_EXISTED" \
  "backup_dir=\$BACKUP" \
  > "\$BACKUP/receipt.env" ||
  die "RECEIPT_WRITE_FAILED"

mkdir -p /usr/local/lib ||
  die "LIBRARY_DIRECTORY_CREATE_FAILED"

TARGET_TMP="\${TARGET}.m07-new.\$\$"
LIB_TMP="\${LIB}.m07-new.\$\$"

rollback_now() {
  rm -f "\$TARGET_TMP" "\$LIB_TMP"

  if [ -s "\$BACKUP/hmn-refresh-pool-safe.sh.before" ]
  then
    cp -p \
      "\$BACKUP/hmn-refresh-pool-safe.sh.before" \
      "\${TARGET}.rollback.\$\$" &&
    mv "\${TARGET}.rollback.\$\$" "\$TARGET"
  fi

  if [ "\$LIB_EXISTED" = "true" ]
  then
    if [ -s "\$BACKUP/router-egress-vm101-runtime.sh.before" ]
    then
      cp -p \
        "\$BACKUP/router-egress-vm101-runtime.sh.before" \
        "\${LIB}.rollback.\$\$" &&
      mv "\${LIB}.rollback.\$\$" "\$LIB"
    fi
  else
    rm -f "\$LIB"
  fi

  sync
}

cp "\$LIB_SRC" "\$LIB_TMP" ||
  die "LIBRARY_STAGE_COPY_FAILED"

chmod 0644 "\$LIB_TMP" ||
  die "LIBRARY_STAGE_MODE_FAILED"

sh -n "\$LIB_TMP" || {
  rollback_now
  die "LIBRARY_STAGE_SYNTAX_FAILED"
}

[ "\$(hash_file "\$LIB_TMP")" = "\$EXPECTED_LIB_AFTER" ] || {
  rollback_now
  die "LIBRARY_STAGE_HASH_FAILED"
}

cp "\$TARGET_SRC" "\$TARGET_TMP" || {
  rollback_now
  die "TARGET_STAGE_COPY_FAILED"
}

chmod 0700 "\$TARGET_TMP" || {
  rollback_now
  die "TARGET_STAGE_MODE_FAILED"
}

sh -n "\$TARGET_TMP" || {
  rollback_now
  die "TARGET_STAGE_SYNTAX_FAILED"
}

[ "\$(hash_file "\$TARGET_TMP")" = "\$EXPECTED_TARGET_AFTER" ] || {
  rollback_now
  die "TARGET_STAGE_HASH_FAILED"
}

mv "\$LIB_TMP" "\$LIB" || {
  rollback_now
  die "LIBRARY_ATOMIC_MOVE_FAILED"
}

mv "\$TARGET_TMP" "\$TARGET" || {
  rollback_now
  die "TARGET_ATOMIC_MOVE_FAILED"
}

sync

[ "\$(hash_file "\$LIB")" = "\$EXPECTED_LIB_AFTER" ] || {
  rollback_now
  die "LIBRARY_FINAL_HASH_FAILED"
}

[ "\$(hash_file "\$TARGET")" = "\$EXPECTED_TARGET_AFTER" ] || {
  rollback_now
  die "TARGET_FINAL_HASH_FAILED"
}

sh -n "\$LIB" || {
  rollback_now
  die "LIBRARY_FINAL_SYNTAX_FAILED"
}

sh -n "\$TARGET" || {
  rollback_now
  die "TARGET_FINAL_SYNTAX_FAILED"
}

printf '%s\n' \
  "installed=true" \
  "target_sha256=\$EXPECTED_TARGET_AFTER" \
  "library_sha256=\$EXPECTED_LIB_AFTER" \
  "backup_dir=\$BACKUP" \
  >> "\$BACKUP/receipt.env"

echo "INSTALL_PASS=true"
echo "target=\$TARGET"
echo "target_sha256=\$EXPECTED_TARGET_AFTER"
echo "library=\$LIB"
echo "library_sha256=\$EXPECTED_LIB_AFTER"
echo "backup_dir=\$BACKUP"
echo "refresh_ran=false"
echo "services_restarted=false"
EOF

cat > "$BUNDLE/verify.sh" <<EOF
#!/bin/sh
set -u

TARGET="/root/hmn/hmn-refresh-pool-safe.sh"
LIB="/usr/local/lib/router-egress-vm101-runtime.sh"

EXPECTED_TARGET="${CANDIDATE_SHA}"
EXPECTED_LIB="${RUNTIME_SHA}"

hash_file() {
  if command -v sha256sum >/dev/null 2>&1
  then
    sha256sum "\$1" |
      awk '{print \$1}'
  else
    busybox sha256sum "\$1" |
      awk '{print \$1}'
  fi
}

[ -s "\$TARGET" ] || exit 1
[ -s "\$LIB" ] || exit 1

[ "\$(hash_file "\$TARGET")" = "\$EXPECTED_TARGET" ] ||
  exit 2

[ "\$(hash_file "\$LIB")" = "\$EXPECTED_LIB" ] ||
  exit 3

sh -n "\$TARGET" || exit 4
sh -n "\$LIB" || exit 5

echo "VERIFY_PASS=true"
echo "target_sha256=\$EXPECTED_TARGET"
echo "library_sha256=\$EXPECTED_LIB"
EOF

cat > "$BUNDLE/rollback.sh" <<'EOF'
#!/bin/sh
set -u

TARGET="/root/hmn/hmn-refresh-pool-safe.sh"
LIB="/usr/local/lib/router-egress-vm101-runtime.sh"

die() {
  echo "ROLLBACK_STOP=$1" >&2
  exit 1
}

[ "$(id -u)" -eq 0 ] ||
  die "ROOT_REQUIRED"

[ "$#" -eq 3 ] ||
  die "USE: rollback.sh --backup DIR CONFIRM_REFRESH_POOL_SAFE_ROLLBACK"

[ "$1" = "--backup" ] ||
  die "BACKUP_FLAG_REQUIRED"

BACKUP="$2"

[ "$3" = "CONFIRM_REFRESH_POOL_SAFE_ROLLBACK" ] ||
  die "CONFIRMATION_INVALID"

[ -s "$BACKUP/receipt.env" ] ||
  die "BACKUP_RECEIPT_MISSING"

[ -s "$BACKUP/hmn-refresh-pool-safe.sh.before" ] ||
  die "TARGET_BACKUP_MISSING"

LIB_EXISTED="$(
  sed -n 's/^library_existed=//p' \
    "$BACKUP/receipt.env" |
  tail -n1
)"

cp -p \
  "$BACKUP/hmn-refresh-pool-safe.sh.before" \
  "${TARGET}.rollback.$$" ||
  die "TARGET_RESTORE_COPY_FAILED"

sh -n "${TARGET}.rollback.$$" ||
  die "TARGET_RESTORE_SYNTAX_FAILED"

mv "${TARGET}.rollback.$$" "$TARGET" ||
  die "TARGET_RESTORE_MOVE_FAILED"

if [ "$LIB_EXISTED" = "true" ]
then
  [ -s "$BACKUP/router-egress-vm101-runtime.sh.before" ] ||
    die "LIBRARY_BACKUP_MISSING"

  cp -p \
    "$BACKUP/router-egress-vm101-runtime.sh.before" \
    "${LIB}.rollback.$$" ||
    die "LIBRARY_RESTORE_COPY_FAILED"

  sh -n "${LIB}.rollback.$$" ||
    die "LIBRARY_RESTORE_SYNTAX_FAILED"

  mv "${LIB}.rollback.$$" "$LIB" ||
    die "LIBRARY_RESTORE_MOVE_FAILED"
else
  rm -f "$LIB"
fi

sync

echo "ROLLBACK_PASS=true"
echo "backup_dir=$BACKUP"
echo "refresh_ran=false"
echo "services_restarted=false"
EOF

cat > "$BUNDLE/README.txt" <<EOF
VM101 M07 single-target install bundle

Target:
  /root/hmn/hmn-refresh-pool-safe.sh

Dependency:
  /usr/local/lib/router-egress-vm101-runtime.sh

Expected live target SHA256 before install:
  ${SOURCE_SHA}

Expected target SHA256 after install:
  ${CANDIDATE_SHA}

Expected runtime library SHA256:
  ${RUNTIME_SHA}

This bundle does not run refresh, rebalance or restart services.

Installation requires the explicit command:

  ./install.sh --apply CONFIRM_REFRESH_POOL_SAFE_R06B

Verification:

  ./verify.sh

Rollback requires the backup directory printed by install.sh:

  ./rollback.sh --backup <directory> CONFIRM_REFRESH_POOL_SAFE_ROLLBACK
EOF

chmod 700 \
  "$BUNDLE/install.sh" \
  "$BUNDLE/verify.sh" \
  "$BUNDLE/rollback.sh"

sh -n "$BUNDLE/install.sh" ||
  stop_step "INSTALL_SCRIPT_SYNTAX_FAILED"

sh -n "$BUNDLE/verify.sh" ||
  stop_step "VERIFY_SCRIPT_SYNTAX_FAILED"

sh -n "$BUNDLE/rollback.sh" ||
  stop_step "ROLLBACK_SCRIPT_SYNTAX_FAILED"

(
  cd "$BUNDLE"

  find . \
    -type f \
    ! -name SHA256SUMS \
    -print0 |
    sort -z |
    xargs -0 sha256sum \
    > SHA256SUMS

  sha256sum -c SHA256SUMS
) > "$REPORT_DIR/bundle-sha256-check.txt" 2>&1 ||
  stop_step "BUNDLE_SHA256_FAILED"

tar -C "$BUNDLE_ROOT" \
  -czf "$ARCHIVE" \
  "$(basename "$BUNDLE")" ||
  stop_step "BUNDLE_ARCHIVE_FAILED"

ARCHIVE_SHA="$(
  sha256sum "$ARCHIVE" |
    cut -d' ' -f1
)"

python3 - \
  "$REPORT_DIR/bundle-manifest-public.json" \
  "$SOURCE_SHA" \
  "$CANDIDATE_SHA" \
  "$RUNTIME_SHA" \
  "$ARCHIVE_SHA" <<'PY'
import json
import sys
from pathlib import Path

(
    output,
    source_sha,
    candidate_sha,
    runtime_sha,
    archive_sha,
) = sys.argv[1:]

Path(output).write_text(
    json.dumps({
        "schema":
            "vm101-refresh-pool-safe-install-bundle-public-v1",

        "target":
            "/root/hmn/hmn-refresh-pool-safe.sh",

        "dependency":
            "/usr/local/lib/router-egress-vm101-runtime.sh",

        "expected_live_target_sha256":
            source_sha,

        "candidate_target_sha256":
            candidate_sha,

        "runtime_library_sha256":
            runtime_sha,

        "archive_sha256":
            archive_sha,

        "contains": [
            "complete target candidate",
            "runtime library",
            "hash-locked installer",
            "read-only verifier",
            "explicit rollback tool",
        ],

        "installer_properties": {
            "requires_explicit_confirmation": True,
            "checks_live_source_hash": True,
            "checks_payload_hashes": True,
            "creates_surgical_backup": True,
            "uses_atomic_replacement": True,
            "rolls_back_on_failure": True,
            "runs_refresh": False,
            "restarts_services": False,
        },

        "payload_public": False,
    }, ensure_ascii=False, indent=2) + "\n",
    encoding="utf-8",
)
PY

BUNDLE_PASS=true
ALL_OK=true

cat > "$WORKFLOW_STATE" <<EOF
M07_WORKFLOW_STATUS=RECOVERY_MODE_SINGLE_TARGET
M07_KNOWN_GOOD_CANONICAL_ID=$(value "$WORKFLOW_STATE" M07_KNOWN_GOOD_CANONICAL_ID)
M07_NEXT_TARGET=refresh_pool_safe
M07_REFRESH_POOL_SAFE_WORKSPACE=${SOURCE_WORKSPACE}
M07_REFRESH_POOL_SAFE_SOURCE_SHA256=${SOURCE_SHA}
M07_REFRESH_POOL_SAFE_CANDIDATE_SHA256=${CANDIDATE_SHA}
M07_REFRESH_POOL_SAFE_STATUS=INSTALL_BUNDLE_READY_NOT_INSTALLED
M07_REFRESH_POOL_SAFE_BUNDLE=${BUNDLE}
M07_REFRESH_POOL_SAFE_ARCHIVE=${ARCHIVE}
M07_REFRESH_POOL_SAFE_ARCHIVE_SHA256=${ARCHIVE_SHA}
M07_NEXT_STEP=VM101_READ_ONLY_INSTALL_PREFLIGHT
EOF

chmod 600 "$WORKFLOW_STATE"

publish_report \
  "PASS" \
  "REFRESH_POOL_SAFE_PRIVATE_DIFF_APPROVED_AND_INSTALL_BUNDLE_BUILT" \
  "NONE"

echo
echo "decision=PASS_${STEP}"
echo "operation_result=REFRESH_POOL_SAFE_PRIVATE_DIFF_APPROVED_AND_INSTALL_BUNDLE_BUILT"
echo "diff_review_pass=$DIFF_REVIEW_PASS"
echo "syntax_pass=$SYNTAX_PASS"
echo "bundle_pass=$BUNDLE_PASS"
echo "bundle=$BUNDLE"
echo "archive=$ARCHIVE"
echo "archive_sha256=$ARCHIVE_SHA"
echo "installation_performed=false"
echo "vm101_contacted=false"
echo "vm101_modified=false"
