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

STEP_ID="${STEP_ID:?}"
STEP_DIR="${STEP_DIR:?}"
STEP_SHA256="${STEP_SHA256:?}"

BASE="/opt/router-ops"
LIVE="$BASE/bin/router-publish-report"
PUBLISHER="$LIVE"
REINDEX="$BASE/bin/router-public-reindex"
TOKEN_FILE="$BASE/public/.router-public-token"

DOMAIN="reports.secret-studio.ru"
CANDIDATE_URL="https://$DOMAIN/latest/20260715-172338_step_direct_https_r04f_candidate_evidence_salvage/router-publish-report.candidate"
EXPECTED_LIVE_SHA256="83582dd85e88032d3aecf8c285cd2ec758a2006ea285fa69c17fa35554a64ea4"
EXPECTED_CANDIDATE_SHA256="e78430b57afbd0ae27fc575fc4de78bb267c76caf04ec935b01e9b2f89840e32"

REPORT="$STEP_DIR/report.txt"
FACTS="$STEP_DIR/facts.json"
VERIFY="$STEP_DIR/verify.txt"
ROLLBACK="$STEP_DIR/rollback.sh"
LOG="$STEP_DIR/main.log"
PROGRESS="$STEP_DIR/progress.log"
MODEL="$STEP_DIR/affected-system-model.txt"
METHODS="$STEP_DIR/methods-and-limitations.txt"
ACCESS="$STEP_DIR/access-routes.txt"
CANDIDATE="$STEP_DIR/router-publish-report.candidate"
BACKUP="$STEP_DIR/router-publish-report.before"
INSTALL_DIFF="$STEP_DIR/install.diff"
PUBLISH_OUT="$STEP_DIR/publisher-output.txt"
PUBLISH_ERR="$STEP_DIR/publisher-errors.txt"
MANIFEST="$STEP_DIR/manifest.sha256"
BEFORE_LATEST="$STEP_DIR/before-latest-step-reports.txt"
BEFORE_OLD="$STEP_DIR/before-old-step-reports.txt"
AFTER_LATEST="$STEP_DIR/after-latest-step-reports.txt"
AFTER_OLD="$STEP_DIR/after-old-step-reports.txt"
MOVED_PREVIOUS="$STEP_DIR/moved-previous-step-reports.txt"
SANDBOX="$STEP_DIR/sandbox"

LOCAL_M07_PLAN_URL="https://$DOMAIN/latest/20260713-193942_local_architecture_plan_vm101_autonomous_hmn_recovery/"
GLOBAL_PROJECT_PLAN_URL="https://$DOMAIN/latest/20260711-123348_global_project_plan_wg_paid/"
ACCESS_MAP_URL="https://$DOMAIN/latest/20260714-092500_access_map_canonical_current/"
VM100_PUBLIC_URL="https://$DOMAIN/latest/20260713-182653_vm100_git_source_097755408853/"
VM101_PUBLIC_URL="https://$DOMAIN/latest/20260713-192042_vm101_git_source_027589515a26/"
VM121_PUBLIC_URL="https://$DOMAIN/latest/20260713-182700_vm121_git_source_93e0e5a31f09/"
VM101_MODEL_URL="https://$DOMAIN/latest/20260713-192030_vm101_model_hmn_download_selector_r13a/"
VM101_METHODS_URL="https://$DOMAIN/latest/20260713-193942_vm101_methods_machine_git_count_contract_r13b/"
VM130_SOURCE_URL="https://$DOMAIN/latest/20260714-085433_vm130_router_ops_source_snapshot_r13f/"
LATEST_ROOT_URL="https://$DOMAIN/latest/"
OLD_ROOT_URL="https://$DOMAIN/old/"

LIVE_CHANGED=false
PUBLICATION_COMMITTED=false
PRIV=()
LIVE_MODE=""
LIVE_UID=""
LIVE_GID=""
PUBLISHED_DIR=""
PUBLISHED_FOLDER=""
TOKEN=""
LATEST=""
OLD=""

exec > >(tee -a "$LOG") 2>&1

progress() {
    printf '>>> [%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$PROGRESS"
}

priv() {
    "${PRIV[@]}" "$@"
}

restore_live() {
    if [[ "$LIVE_CHANGED" == true && -f "$BACKUP" ]]; then
        local tmp="${LIVE}.rollback.${STEP_ID}.$$"
        priv install             -o "$LIVE_UID"             -g "$LIVE_GID"             -m "$LIVE_MODE"             "$BACKUP" "$tmp"
        priv mv -f "$tmp" "$LIVE"
        LIVE_CHANGED=false
    fi
}

stop_step() {
    local result="$1"
    local reason="$2"
    set +e
    if [[ "$PUBLICATION_COMMITTED" == false ]]; then
        restore_live
    fi
    cat > "$REPORT" <<EOF_STOP
RESULT=$result
STEP_ID=$STEP_ID
STOP_REASON=$reason
STEP_REPORT_URL=PENDING_NOT_PUBLISHED
COPY_VERIFY=PASS
STEP_SHA256=$STEP_SHA256
STEP_WAS_NOT_STARTED=false
RUNTIME_IMPACT=false
ROLLBACK_REQUIRED=$LIVE_CHANGED
EOF_STOP
    printf 'RESULT=%s\n' "$result"
    printf 'STOP_REASON=%s\n' "$reason"
    printf 'STEP_REPORT_URL=PENDING_NOT_PUBLISHED\n'
    printf 'COPY_VERIFY=PASS\n'
    printf 'STEP_SHA256=%s\n' "$STEP_SHA256"
    printf 'STEP_WAS_NOT_STARTED=false\n'
    printf 'RUNTIME_IMPACT=false\n'
    exit 20
}

progress "preflight"

for cmd in curl sha256sum sh cmp diff stat cp mv chmod find awk grep sed flock python3 install id; do
    command -v "$cmd" >/dev/null 2>&1 ||
        stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "missing_command_$cmd"
done

[[ -x "$LIVE" ]] ||
    stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "live_publisher_missing"

LIVE_MODE="$(stat -c '%a' "$LIVE")"
LIVE_UID="$(stat -c '%u' "$LIVE")"
LIVE_GID="$(stat -c '%g' "$LIVE")"

if [[ ! -w "$(dirname "$LIVE")" ||
      "$(id -u)" != "$LIVE_UID" ]]; then
    command -v sudo >/dev/null 2>&1 ||
        stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "sudo_missing"
    sudo -n true >/dev/null 2>&1 ||
        stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "passwordless_sudo_unavailable"
    PRIV=(sudo -n)
fi

[[ -x "$REINDEX" ]] ||
    stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "reindex_missing"

[[ -s "$TOKEN_FILE" ]] ||
    stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "token_missing"

TOKEN="$(cat "$TOKEN_FILE")"
ROOT="$BASE/public/r/$TOKEN"
LATEST="$ROOT/latest"
OLD="$ROOT/old"

[[ -d "$LATEST" && -d "$OLD" ]] ||
    stop_step "STOP_INSTALL_PREFLIGHT_FAILED" "latest_or_old_missing"

LIVE_SHA256_BEFORE="$(sha256sum "$LIVE" | awk '{print $1}')"
[[ "$LIVE_SHA256_BEFORE" == "$EXPECTED_LIVE_SHA256" ]] ||
    stop_step "STOP_LIVE_SOURCE_CHANGED" "$LIVE_SHA256_BEFORE"

progress "downloading already published candidate"

curl --resolve reports.secret-studio.ru:443:10.71.100.84 -fsSL --connect-timeout 10 --max-time 60 \
    "$CANDIDATE_URL" -o "$CANDIDATE" ||
    stop_step "STOP_CANDIDATE_DOWNLOAD_FAILED" "$CANDIDATE_URL"

chmod 700 "$CANDIDATE"

CANDIDATE_SHA256="$(sha256sum "$CANDIDATE" | awk '{print $1}')"
[[ "$CANDIDATE_SHA256" == "$EXPECTED_CANDIDATE_SHA256" ]] ||
    stop_step "STOP_CANDIDATE_SHA256_MISMATCH" "$CANDIDATE_SHA256"

sh -n "$CANDIDATE" ||
    stop_step "STOP_CANDIDATE_SYNTAX_FAILED" "sh_n"

cp "$LIVE" "$BACKUP"
chmod 600 "$BACKUP"

set +e
diff -u \
    --label before/router-publish-report \
    --label candidate/router-publish-report \
    "$BACKUP" "$CANDIDATE" > "$INSTALL_DIFF"
DIFF_RC=$?
set -e
[[ "$DIFF_RC" -eq 1 ]] ||
    stop_step "STOP_INSTALL_DIFF_INVALID" "$DIFF_RC"

progress "atomic publisher installation"

INSTALL_TMP="${LIVE}.install.${STEP_ID}.$$"

priv install     -o "$LIVE_UID"     -g "$LIVE_GID"     -m "$LIVE_MODE"     "$CANDIDATE" "$INSTALL_TMP"
priv mv -f "$INSTALL_TMP" "$LIVE"
LIVE_CHANGED=true

LIVE_SHA256_AFTER="$(sha256sum "$LIVE" | awk '{print $1}')"
[[ "$LIVE_SHA256_AFTER" == "$EXPECTED_CANDIDATE_SHA256" ]] ||
    stop_step "STOP_INSTALLED_SHA256_MISMATCH" "$LIVE_SHA256_AFTER"

sh -n "$LIVE" ||
    stop_step "STOP_INSTALLED_SYNTAX_FAILED" "sh_n"

progress "isolated post-install contract test"

TEST_BASE="$SANDBOX/router-ops"
TEST_TOKEN="0123456789abcdef0123456789abcdef0123456789abcdef"
TEST_ROOT="$TEST_BASE/public/r/$TEST_TOKEN"
mkdir -p "$TEST_BASE/bin" "$TEST_BASE/state/locks" "$TEST_BASE/public"
cp -a "$LIVE" "$TEST_BASE/bin/router-publish-report"
printf '%s\n' "$TEST_TOKEN" > "$TEST_BASE/public/.router-public-token"
printf 'installed publisher probe\n' > "$SANDBOX/probe.txt"

ROUTER_OPS_BASE="$TEST_BASE" \
ROUTER_PUBLIC_TOKEN="$TEST_TOKEN" \
ROUTER_PUBLIC_ROOT="$TEST_ROOT" \
ROUTER_PUBLIC_REINDEX="/bin/true" \
ROUTER_PUBLIC_BASE_URL="https://$DOMAIN" \
"$TEST_BASE/bin/router-publish-report" \
    "step_installed_publisher_probe" \
    "$SANDBOX/probe.txt" > "$SANDBOX/output.txt"

SANDBOX_STEP_REPORT_URL="$(
    awk -F= '$1=="STEP_REPORT_URL" {print substr($0,index($0,"=")+1)}' \
        "$SANDBOX/output.txt" | tail -n 1
)"
SANDBOX_KIND="$(
    awk -F= '$1=="PUBLIC_OBJECT_KIND" {print $2}' \
        "$SANDBOX/output.txt" | tail -n 1
)"

[[ "$SANDBOX_STEP_REPORT_URL" == "https://$DOMAIN/latest/"*"/" ]] ||
    stop_step "STOP_INSTALLED_CONTRACT_TEST_FAILED" "permanent_step_report_url"

[[ "$SANDBOX_KIND" == "step-report" ]] ||
    stop_step "STOP_INSTALLED_CONTRACT_TEST_FAILED" "object_kind"

find "$LATEST" -mindepth 1 -maxdepth 1 -type d -name '*_step*' -printf '%f\n' |
    LC_ALL=C sort > "$BEFORE_LATEST"
find "$OLD" -mindepth 1 -maxdepth 1 -type d -name '*_step*' -printf '%f\n' |
    LC_ALL=C sort > "$BEFORE_OLD"

cat > "$MODEL" <<EOF_MODEL
AFFECTED_SYSTEM=VM130 router report publication path
LIVE_FILE=$LIVE
BEFORE_SHA256=$LIVE_SHA256_BEFORE
AFTER_SHA256=$LIVE_SHA256_AFTER
CADDY_CHANGE=false
SERVICE_CHANGE=false
NETWORK_CHANGE=false
PUBLICATION_OUTPUT_CHANGE=permanent canonical HTTPS URLs added
LEGACY_TRYCLOUDFLARE_OUTPUT=temporarily preserved
EOF_MODEL

cat > "$METHODS" <<EOF_METHODS
DELIVERY_METHOD=short terminal bootstrap plus HTTPS candidate download
CANDIDATE_SOURCE=$CANDIDATE_URL
CANDIDATE_SHA256=$CANDIDATE_SHA256
TRANSFER_INTEGRITY=SHA256 plus sh -n
INSTALL_METHOD=atomic same-filesystem rename
POSTCHECK=installed SHA256, sh -n, isolated contract test, real publication, HTTP
LIMITATION=Fresh VM130 source snapshot and Access Map refresh are separate next STEPs.
EOF_METHODS

cat > "$ACCESS" <<EOF_ACCESS
VM130=10.71.100.84
PUBLIC_DOMAIN=https://$DOMAIN/
LATEST_ROOT_URL=$LATEST_ROOT_URL
OLD_ROOT_URL=$OLD_ROOT_URL
ACCESS_MAP_STATUS=previous confirmed object; permanent route refresh required next STEP
EOF_ACCESS

cat > "$REPORT" <<EOF_REPORT_PRE
RESULT=PENDING_PUBLICATION
STEP_ID=$STEP_ID
SOURCE_CODE_CHANGE=true
RUNTIME_IMPACT=false
EOF_REPORT_PRE

cat > "$VERIFY" <<EOF_VERIFY_PRE
STEP_ID=$STEP_ID
RESULT=PENDING_PUBLICATION
LIVE_SHA256_BEFORE=$LIVE_SHA256_BEFORE
LIVE_SHA256_AFTER=$LIVE_SHA256_AFTER
CANDIDATE_SHA256=$CANDIDATE_SHA256
INSTALLED_SYNTAX=PASS
SANDBOX_STEP_REPORT_URL=$SANDBOX_STEP_REPORT_URL
EOF_VERIFY_PRE

python3 - "$FACTS" <<EOF_FACTS_PRE
import json
from pathlib import Path
Path("$FACTS").write_text(json.dumps({
  "step_id": "$STEP_ID",
  "result": "PENDING_PUBLICATION",
  "source_code_change": True,
  "runtime_impact": False
}, indent=2) + "\n", encoding="utf-8")
EOF_FACTS_PRE

cat > "$ROLLBACK" <<EOF_ROLLBACK_PRE
#!/usr/bin/env bash
set -Eeuo pipefail
LIVE="$LIVE"
BACKUP="$BACKUP"
EXPECTED_BACKUP_SHA256="$LIVE_SHA256_BEFORE"
LIVE_MODE="$LIVE_MODE"
LIVE_UID="$LIVE_UID"
LIVE_GID="$LIVE_GID"
REINDEX="$REINDEX"
PRIV=()

if [[ ! -w "\$(dirname "\$LIVE")" ||
      "\$(id -u)" != "\$LIVE_UID" ]]; then
    PRIV=(sudo -n)
fi

priv() {
    "\${PRIV[@]}" "\$@"
}

[[ -f "\$BACKUP" ]] || {
    echo "RESULT=STOP_ROLLBACK_BACKUP_MISSING"
    exit 20
}

TMP="\${LIVE}.rollback.\$(date +%s).tmp"
priv install \
    -o "\$LIVE_UID" \
    -g "\$LIVE_GID" \
    -m "\$LIVE_MODE" \
    "\$BACKUP" "\$TMP"
priv mv -f "\$TMP" "\$LIVE"

ACTUAL="\$(sha256sum "\$LIVE" | awk '{print \$1}')"
[[ "\$ACTUAL" == "\$EXPECTED_BACKUP_SHA256" ]] || {
    echo "RESULT=STOP_ROLLBACK_SHA256_MISMATCH"
    echo "ACTUAL_SHA256=\$ACTUAL"
    exit 21
}

sh -n "\$LIVE"
"\$REINDEX"

echo "RESULT=PASS_PUBLISHER_ROLLBACK"
echo "RESTORED_SHA256=\$ACTUAL"
echo "RUNTIME_IMPACT=false"
EOF_ROLLBACK_PRE
chmod 700 "$ROLLBACK"

: > "$PUBLISH_OUT"
: > "$PUBLISH_ERR"
: > "$MANIFEST"

progress "real publication through installed publisher"

set +e
ROUTER_PUBLIC_BASE_URL="https://$DOMAIN" \
"$PUBLISHER" \
    "step_direct_https_publisher_install_r04i" \
    "$STEP_DIR/step-code.sh" \
    "$STEP_DIR/transfer-verify.txt" \
    "$REPORT" "$FACTS" "$VERIFY" "$ROLLBACK" \
    "$LOG" "$PROGRESS" "$MODEL" "$METHODS" "$ACCESS" \
    "$CANDIDATE" "$BACKUP" "$INSTALL_DIFF" \
    "$PUBLISH_OUT" "$PUBLISH_ERR" "$MANIFEST" \
    > "$STEP_DIR/publisher-command-output.txt" \
    2> "$STEP_DIR/publisher-command-errors.txt"
PUBLISH_RC=$?
set -e

[[ "$PUBLISH_RC" -eq 0 ]] ||
    stop_step "STOP_REAL_PUBLICATION_FAILED" "$STEP_DIR/publisher-command-errors.txt"

PUBLISHED_DIR="$(
    awk -F= '$1=="PUBLISHED_DIR" {print substr($0,index($0,"=")+1)}' \
        "$STEP_DIR/publisher-command-output.txt" | tail -n 1
)"
STEP_REPORT_URL="$(
    awk -F= '$1=="STEP_REPORT_URL" {print substr($0,index($0,"=")+1)}' \
        "$STEP_DIR/publisher-command-output.txt" | tail -n 1
)"
PUBLIC_OBJECT_KIND="$(
    awk -F= '$1=="PUBLIC_OBJECT_KIND" {print $2}' \
        "$STEP_DIR/publisher-command-output.txt" | tail -n 1
)"
PREVIOUS_MOVED_COUNT="$(
    awk -F= '$1=="PREVIOUS_MOVED_COUNT" {print $2}' \
        "$STEP_DIR/publisher-command-output.txt" | tail -n 1
)"

[[ -d "$PUBLISHED_DIR" ]] ||
    stop_step "STOP_PUBLISHED_DIR_MISSING" "$PUBLISHED_DIR"

[[ "$STEP_REPORT_URL" == "https://$DOMAIN/latest/"*"/" ]] ||
    stop_step "STOP_PERMANENT_URL_OUTPUT_INVALID" "$STEP_REPORT_URL"

[[ "$PUBLIC_OBJECT_KIND" == "step-report" ]] ||
    stop_step "STOP_PUBLIC_OBJECT_KIND_INVALID" "$PUBLIC_OBJECT_KIND"

PUBLICATION_COMMITTED=true
PUBLISHED_FOLDER="$(basename "$PUBLISHED_DIR")"

find "$LATEST" -mindepth 1 -maxdepth 1 -type d -name '*_step*' -printf '%f\n' |
    LC_ALL=C sort > "$AFTER_LATEST"
find "$OLD" -mindepth 1 -maxdepth 1 -type d -name '*_step*' -printf '%f\n' |
    LC_ALL=C sort > "$AFTER_OLD"
comm -13 "$BEFORE_OLD" "$AFTER_OLD" > "$MOVED_PREVIOUS"

CURRENT_STEP_REPORT_COUNT="$(wc -l < "$AFTER_LATEST" | tr -d ' ')"
ACTUAL_MOVED_COUNT="$(wc -l < "$MOVED_PREVIOUS" | tr -d ' ')"

FACTS_URL="${STEP_REPORT_URL}facts.json"
VERIFY_URL="${STEP_REPORT_URL}verify.txt"
ROLLBACK_URL="${STEP_REPORT_URL}rollback.sh"

cat >> "$ROLLBACK" <<EOF_ROLLBACK_PUBLICATION

# Publication-state rollback for this STEP.
PUBLISHED_DIR="$PUBLISHED_DIR"
LATEST="$LATEST"
OLD="$OLD"
PUBLISHED_FOLDER="$PUBLISHED_FOLDER"

if [[ -d "\$PUBLISHED_DIR" ]]; then
    mv "\$PUBLISHED_DIR" \
       "\$OLD/\$(date +%Y%m%d-%H%M%S)_rollback_removed_\$PUBLISHED_FOLDER"
fi

while IFS= read -r name; do
    [[ -n "\$name" ]] || continue
    [[ -d "\$OLD/\$name" ]] || continue
    mv "\$OLD/\$name" "\$LATEST/\$name"
done <<'EOF_MOVED'
$(cat "$MOVED_PREVIOUS")
EOF_MOVED

"\$REINDEX"
EOF_ROLLBACK_PUBLICATION

cat > "$REPORT" <<EOF_REPORT
RESULT=PASS_PERMANENT_PUBLISHER_INSTALLED
STEP_ID=$STEP_ID
STEP_REPORT_URL=$STEP_REPORT_URL
LOCAL_M07_PLAN_URL=$LOCAL_M07_PLAN_URL
GLOBAL_PROJECT_PLAN_URL=$GLOBAL_PROJECT_PLAN_URL
ACCESS_MAP_URL=$ACCESS_MAP_URL
VM100_PUBLIC_URL=$VM100_PUBLIC_URL
VM101_PUBLIC_URL=$VM101_PUBLIC_URL
VM121_PUBLIC_URL=$VM121_PUBLIC_URL
VM101_MODEL_URL=$VM101_MODEL_URL
VM101_METHODS_URL=$VM101_METHODS_URL
VM130_SOURCE_URL=$VM130_SOURCE_URL
LATEST_ROOT_URL=$LATEST_ROOT_URL
OLD_ROOT_URL=$OLD_ROOT_URL
FACTS_URL=$FACTS_URL
VERIFY_URL=$VERIFY_URL
ROLLBACK_URL=$ROLLBACK_URL
PUBLIC_OBJECT_KIND=$PUBLIC_OBJECT_KIND
PREVIOUS_MOVED_COUNT=$PREVIOUS_MOVED_COUNT
COPY_VERIFY=PASS
STEP_SHA256=$STEP_SHA256
LIVE_SHA256_BEFORE=$LIVE_SHA256_BEFORE
LIVE_SHA256_AFTER=$LIVE_SHA256_AFTER
EXPECTED_SHA256=$EXPECTED_CANDIDATE_SHA256
ACTUAL_SHA256=$LIVE_SHA256_AFTER
CANDIDATE_SOURCE_URL=$CANDIDATE_URL
SOURCE_CODE_CHANGE=true
GIT_STATUS=not_applicable_vm130_snapshot_workflow
VM130_SOURCE_STATUS=previous_pre_change_snapshot; fresh snapshot required next STEP
ACCESS_MAP_STATUS=previous confirmed object; route refresh required next STEP
CADDY_CHANGE=false
SERVICE_CHANGE=false
RUNTIME_IMPACT=false
TRAFFIC_INTERRUPTION=none
ROLLBACK_REQUIRED=true
CORE_POSTCHECK=PASS
EXTERNAL_POSTCHECK=PENDING_ASSISTANT
EOF_REPORT

python3 - "$FACTS" <<EOF_FACTS
import json
from pathlib import Path
facts = {
  "step_id": "$STEP_ID",
  "result": "PASS_PERMANENT_PUBLISHER_INSTALLED",
  "step_report_url": "$STEP_REPORT_URL",
  "copy_verify": "PASS",
  "step_sha256": "$STEP_SHA256",
  "source_code_change": True,
  "runtime_impact": False,
  "live": {
    "before_sha256": "$LIVE_SHA256_BEFORE",
    "after_sha256": "$LIVE_SHA256_AFTER",
    "expected_sha256": "$EXPECTED_CANDIDATE_SHA256",
    "match": "$LIVE_SHA256_AFTER" == "$EXPECTED_CANDIDATE_SHA256",
    "syntax": "PASS"
  },
  "contract_test": {
    "step_report_url": "$SANDBOX_STEP_REPORT_URL",
    "object_kind": "$SANDBOX_KIND",
    "pass": True
  },
  "publication": {
    "object_kind": "$PUBLIC_OBJECT_KIND",
    "previous_moved_count": int("$PREVIOUS_MOVED_COUNT"),
    "actual_moved_count": int("$ACTUAL_MOVED_COUNT"),
    "current_step_report_count": int("$CURRENT_STEP_REPORT_COUNT")
  },
  "vm130_source_status": "fresh snapshot required next STEP",
  "access_map_status": "refresh required next STEP",
  "external_postcheck": "PENDING_ASSISTANT"
}
Path("$FACTS").write_text(
    json.dumps(facts, indent=2, ensure_ascii=False) + "\n",
    encoding="utf-8"
)
EOF_FACTS

cat > "$VERIFY" <<EOF_VERIFY
STEP_ID=$STEP_ID
RESULT=PASS_PERMANENT_PUBLISHER_INSTALLED
LIVE_SHA256_BEFORE=$LIVE_SHA256_BEFORE
LIVE_SHA256_AFTER=$LIVE_SHA256_AFTER
EXPECTED_SHA256=$EXPECTED_CANDIDATE_SHA256
ACTUAL_SHA256=$LIVE_SHA256_AFTER
INSTALLED_SHA256_MATCH=true
INSTALLED_SYNTAX=PASS
SANDBOX_STEP_REPORT_URL=$SANDBOX_STEP_REPORT_URL
SANDBOX_OBJECT_KIND=$SANDBOX_KIND
SANDBOX_POSTCHECK=PASS
STEP_REPORT_URL=$STEP_REPORT_URL
PERMANENT_URL_OUTPUT=PASS
PUBLIC_OBJECT_KIND=$PUBLIC_OBJECT_KIND
PREVIOUS_MOVED_COUNT=$PREVIOUS_MOVED_COUNT
ACTUAL_MOVED_COUNT=$ACTUAL_MOVED_COUNT
CURRENT_STEP_REPORT_COUNT=$CURRENT_STEP_REPORT_COUNT
CORE_POSTCHECK=PASS
EXTERNAL_POSTCHECK=PENDING_ASSISTANT
RUNTIME_IMPACT=false
EOF_VERIFY

for file in \
    "$STEP_DIR/step-code.sh" "$STEP_DIR/transfer-verify.txt" \
    "$REPORT" "$FACTS" "$VERIFY" "$ROLLBACK" \
    "$LOG" "$PROGRESS" "$MODEL" "$METHODS" "$ACCESS" \
    "$CANDIDATE" "$BACKUP" "$INSTALL_DIFF" \
    "$PUBLISH_OUT" "$PUBLISH_ERR"
do
    printf '%s  %s\n' \
        "$(sha256sum "$file" | awk '{print $1}')" \
        "$(basename "$file")"
done | LC_ALL=C sort > "$MANIFEST"

for file in "$REPORT" "$FACTS" "$VERIFY" "$ROLLBACK" "$MANIFEST"; do
    cp -a "$file" "$PUBLISHED_DIR/$(basename "$file")"
done
chmod 644 "$PUBLISHED_DIR/report.txt" \
          "$PUBLISHED_DIR/facts.json" \
          "$PUBLISHED_DIR/verify.txt" \
          "$PUBLISHED_DIR/manifest.sha256"
chmod 755 "$PUBLISHED_DIR/rollback.sh"
"$REINDEX"

progress "HTTP and publication post-check"

http_code() {
    curl -sS --connect-timeout 5 --max-time 20 \
        --resolve "$DOMAIN:443:10.71.100.84" \
        -o /dev/null -w '%{http_code}' "$1" 2>/dev/null || true
}

FOLDER_CODE="$(http_code "$STEP_REPORT_URL")"
REPORT_CODE="$(http_code "${STEP_REPORT_URL}report.txt")"
FACTS_CODE="$(http_code "$FACTS_URL")"
VERIFY_CODE="$(http_code "$VERIFY_URL")"
ROLLBACK_CODE="$(http_code "$ROLLBACK_URL")"
LATEST_CODE="$(http_code "$LATEST_ROOT_URL")"
OLD_CODE="$(http_code "$OLD_ROOT_URL")"

FINAL_POSTCHECK=FAIL
if [[ "$FOLDER_CODE" == "200" &&
      "$REPORT_CODE" == "200" &&
      "$FACTS_CODE" == "200" &&
      "$VERIFY_CODE" == "200" &&
      "$ROLLBACK_CODE" == "200" &&
      "$LATEST_CODE" == "200" &&
      "$OLD_CODE" == "200" &&
      "$CURRENT_STEP_REPORT_COUNT" -eq 1 &&
      "$ACTUAL_MOVED_COUNT" -eq "$PREVIOUS_MOVED_COUNT" &&
      "$(sha256sum "$LIVE" | awk '{print $1}')" == "$EXPECTED_CANDIDATE_SHA256" ]]; then
    FINAL_POSTCHECK=PASS
fi

if [[ "$FINAL_POSTCHECK" != "PASS" ]]; then
    echo "FINAL_POSTCHECK=FAIL" >> "$VERIFY"
    cp -a "$VERIFY" "$PUBLISHED_DIR/verify.txt"
    stop_step "STOP_POST_INSTALL_POSTCHECK_FAILED" "$VERIFY"
fi

echo "FINAL_POSTCHECK=PASS" >> "$VERIFY"
cp -a "$VERIFY" "$PUBLISHED_DIR/verify.txt"
COMMITTED=true

progress "publisher installation verified"

printf 'RESULT=PASS_PERMANENT_PUBLISHER_INSTALLED\n'
printf 'STEP_REPORT_URL=%s\n' "$STEP_REPORT_URL"
printf 'LOCAL_M07_PLAN_URL=%s\n' "$LOCAL_M07_PLAN_URL"
printf 'GLOBAL_PROJECT_PLAN_URL=%s\n' "$GLOBAL_PROJECT_PLAN_URL"
printf 'ACCESS_MAP_URL=%s\n' "$ACCESS_MAP_URL"
printf 'VM100_PUBLIC_URL=%s\n' "$VM100_PUBLIC_URL"
printf 'VM101_PUBLIC_URL=%s\n' "$VM101_PUBLIC_URL"
printf 'VM121_PUBLIC_URL=%s\n' "$VM121_PUBLIC_URL"
printf 'VM101_MODEL_URL=%s\n' "$VM101_MODEL_URL"
printf 'VM101_METHODS_URL=%s\n' "$VM101_METHODS_URL"
printf 'VM130_SOURCE_URL=%s\n' "$VM130_SOURCE_URL"
printf 'COPY_VERIFY=PASS\n'
printf 'STEP_SHA256=%s\n' "$STEP_SHA256"
printf 'RUNTIME_IMPACT=false\n'
printf 'EXTERNAL_POSTCHECK=PENDING_ASSISTANT\n'
