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

BUNDLE_DIR="$(cd "$(dirname "$0")" && pwd -P)"
SELF="$(readlink -f "$0")"
BUNDLE_ZIP="${BUNDLE_ZIP:?BUNDLE_ZIP is required}"
EXPECTED_BUNDLE_SHA256="${EXPECTED_BUNDLE_SHA256:?EXPECTED_BUNDLE_SHA256 is required}"
EXPECTED_INSTALLER_SHA256="${EXPECTED_INSTALLER_SHA256:?EXPECTED_INSTALLER_SHA256 is required}"
BASE="${ROUTER_OPS_BASE:-/opt/router-ops}"
SSH_BIN="${SSH_BIN:-ssh}"
STEP_ID='STEP_050M07R20F_R02_ACTIVE_OPERATION_QUIESCE_AND_CLOCK_PATCH_CONTINUATION'
BUNDLE_ID='WG_PAID_MGTS_STEP_050M07R20F_R02'
PUBLISH_TS="$(date -u +%Y%m%d-%H%M%S)"
STEP_DIR_BASE="${R20F_RUN_BASE:-$BASE/steps}"
STEP_DIR="$STEP_DIR_BASE/${PUBLISH_TS}_${STEP_ID}"
COMPONENTS="$STEP_DIR/components"
PHASE_CURRENT="$STEP_DIR/phase-current.txt"
PHASE_EVENTS="$STEP_DIR/phase-events.log"
TRANSITION_FILE="$STEP_DIR/runtime-transition.env"
MAIN_LOG="$STEP_DIR/main.log"
PROGRESS_LOG="$STEP_DIR/progress.log"
TRANSFER="$STEP_DIR/transfer-verify.txt"
STEP_FILE="$STEP_DIR/step-code.sh"
BUNDLE_COPY="$STEP_DIR/$(basename "$BUNDLE_ZIP")"
STOP_GUARD_DIR="$STEP_DIR/.stop-handler-active"
mkdir -p "$STEP_DIR" "$COMPONENTS"
chmod 700 "$STEP_DIR" "$COMPONENTS"
cp -a "$SELF" "$STEP_FILE"
chmod 700 "$STEP_FILE"
cp -a "$BUNDLE_ZIP" "$BUNDLE_COPY"
exec 3>&1
exec > >(tee -a "$MAIN_LOG") 2>&1
LOG_TEE_PID=$!

PUBLISHER="$BASE/bin/router-publish-report"
HTTP="$BASE/bin/router-http-verify"
FINALIZER="$BASE/bin/router-step-finalize"
SAFE_BUILDER="$BASE/bin/router-public-safe-payload"
HTML_BUILDER="$BASE/bin/router-public-html-aliases"
WORKFLOW_LIB="$BASE/lib/router-step-workflow.sh"
CONTRACT_LIB="$BASE/lib/router-publication-contract.sh"
RUNTIME_TRANSITION_LIB="$BASE/lib/router-runtime-transition.sh"

RESULT='STOP_R20F_NOT_STARTED'
STOP_REASON='not_started'
CURRENT_PHASE='not_started'
COPY_VERIFY=FAIL
HTTP_VERIFY_PASS=false
PUBLICATION_BARRIER=none
PUBLIC_OBJECT_KIND=step-report
PREVIOUS_MOVED_COUNT=0
RUNTIME_IMPACT=true
CORE_CHANGE_COMPLETE=false
CORE_CHANGE_REPEATED=false
TARGET_INSTALLER_RERUN=false
ROUTER_MACHINE_CLOSE_RERUN=false
SSH_SESSION_REMAINS_OPEN=true
RETRY_DEFERRED_FOR_CONTROLLED_TEST=false
CURRENT_MODE=unknown
BACKUP_READY=false
AUTO_ROLLBACK_ALLOWED=true
WORKFLOW_READY=false
GIT_COMMIT=''
GIT_TREE=''
GIT_FILE_COUNT=''
VM101_PUBLIC_URL='https://reports.secret-studio.ru/latest/20260720-124228_vm101_git_source_1571dd60b780/'
VM130_SOURCE_URL='https://reports.secret-studio.ru/latest/20260720-093614_vm130_router_ops_source_snapshot_after_r20c_full_contract/'
VM101_MODEL_URL='https://reports.secret-studio.ru/latest/20260720-124228_vm101_model_r20d_logging_and_durability_hardening/'
VM101_METHODS_URL='https://reports.secret-studio.ru/latest/20260720-124228_vm101_methods_r20d_logging_and_durability_hardening/'
PROJECT_SOURCE_POST_URL='PENDING_NOT_PUBLISHED'
PROJECT_SOURCE_POST_FILE_URL='PENDING_NOT_PUBLISHED'
STEP_REPORT_URL='PENDING_NOT_PUBLISHED'
FACTS_URL='PENDING_NOT_PUBLISHED'
VERIFY_URL='PENDING_NOT_PUBLISHED'
ROLLBACK_URL='PENDING_NOT_PUBLISHED'
LOCAL_M07_PLAN_URL='https://reports.secret-studio.ru/latest/20260719-080444_local_architecture_plan_vm101_autonomous_hmn_recovery_r19/'
GLOBAL_PROJECT_PLAN_URL='https://reports.secret-studio.ru/latest/20260711-123348_global_project_plan_wg_paid/'
ACCESS_MAP_URL='https://reports.secret-studio.ru/latest/20260715-210236_access_map_canonical_current/'
VM100_PUBLIC_URL='https://reports.secret-studio.ru/latest/20260715-190653_vm100_git_source_1958200ccc1b/'
VM121_PUBLIC_URL='https://reports.secret-studio.ru/latest/20260713-182700_vm121_git_source_93e0e5a31f09/'
LATEST_ROOT_URL='https://reports.secret-studio.ru/latest/'
OLD_ROOT_URL='https://reports.secret-studio.ru/old/'
SNAPSHOT_NAME="r20f2-pre-$(date -u +%m%d-%H%M%S)"
BACKUP_DIR="/root/router-egress-r20f-backup-${PUBLISH_TS}"
REMOTE_STAGE="/tmp/router-egress-r20f-${PUBLISH_TS}"

VM130_LABEL='vm130_router_ops_source_snapshot_after_r20f_clock_hardening_r02'
MODEL_LABEL='vm101_model_r20f_clock_hardening_r02'
METHODS_LABEL='vm101_methods_r20f_clock_hardening_r02'
PROJECT_LABEL='project_source_post_vm101_refresh_clock_hardening_r20f_r02'
STEP_LABEL='step050m07r20f_r02_refresh_clock_hardening'
PUBLIC_BASE='https://reports.secret-studio.ru'
export ROUTER_PUBLISH_TIMESTAMP_OVERRIDE="$PUBLISH_TS"

cleanup() {
    local rc="${1:-1}"
    trap - EXIT INT TERM HUP
    exec 1>&- 2>&- || true
    wait "$LOG_TEE_PID" 2>/dev/null || true
    exit "$rc"
}
trap 'cleanup "$?"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
trap 'exit 129' HUP

progress() {
    local msg
    msg="$*"
    printf '>>> [%s] %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$msg" | tee -a "$PROGRESS_LOG"
}

field() {
    local file
    local key
    file="$1"
    key="$2"
    awk -F= -v k="$key" '$1==k{v=substr($0,index($0,"=")+1)} END{print v}' "$file"
}

emit_final() {
    local step_sha
    step_sha="$(sha256sum "$STEP_FILE" | awk '{print $1}')"
    for line in \
      "RESULT=$RESULT" \
      "STEP_REPORT_URL=$STEP_REPORT_URL" \
      "PROJECT_SOURCE_POST_URL=$PROJECT_SOURCE_POST_URL" \
      "PROJECT_SOURCE_POST_FILE_URL=$PROJECT_SOURCE_POST_FILE_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=$COPY_VERIFY" \
      "STEP_SHA256=$step_sha" \
      "HTTP_VERIFY_PASS=$HTTP_VERIFY_PASS" \
      "RUNTIME_IMPACT=$RUNTIME_IMPACT" \
      "CORE_CHANGE_COMPLETE=$CORE_CHANGE_COMPLETE" \
      "CORE_CHANGE_REPEATED=$CORE_CHANGE_REPEATED" \
      "TARGET_INSTALLER_RERUN=$TARGET_INSTALLER_RERUN" \
      "ROUTER_MACHINE_CLOSE_RERUN=$ROUTER_MACHINE_CLOSE_RERUN" \
      "SSH_SESSION_REMAINS_OPEN=$SSH_SESSION_REMAINS_OPEN" \
      "RETRY_DEFERRED_FOR_CONTROLLED_TEST=$RETRY_DEFERRED_FOR_CONTROLLED_TEST" \
      "CURRENT_MODE=$CURRENT_MODE"
    do
        printf '%s\n' "$line" >&3
    done
}

write_final_env() {
    local out
    local tmp
    out="$1"
    tmp="${out}.tmp.$$"
    {
      printf 'RESULT=%s\n' "$RESULT"
      printf 'STOP_REASON=%s\n' "$STOP_REASON"
      printf 'CURRENT_PHASE=%s\n' "$CURRENT_PHASE"
      printf 'STEP_REPORT_URL=%s\n' "$STEP_REPORT_URL"
      printf 'PROJECT_SOURCE_POST_URL=%s\n' "$PROJECT_SOURCE_POST_URL"
      printf 'PROJECT_SOURCE_POST_FILE_URL=%s\n' "$PROJECT_SOURCE_POST_FILE_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 'LATEST_ROOT_URL=%s\n' "$LATEST_ROOT_URL"
      printf 'OLD_ROOT_URL=%s\n' "$OLD_ROOT_URL"
      printf 'COPY_VERIFY=%s\n' "$COPY_VERIFY"
      printf 'HTTP_VERIFY_PASS=%s\n' "$HTTP_VERIFY_PASS"
      printf 'RUNTIME_IMPACT=%s\n' "$RUNTIME_IMPACT"
      printf 'CORE_CHANGE_COMPLETE=%s\n' "$CORE_CHANGE_COMPLETE"
      printf 'CORE_CHANGE_REPEATED=%s\n' "$CORE_CHANGE_REPEATED"
      printf 'TARGET_INSTALLER_RERUN=%s\n' "$TARGET_INSTALLER_RERUN"
      printf 'ROUTER_MACHINE_CLOSE_RERUN=%s\n' "$ROUTER_MACHINE_CLOSE_RERUN"
      printf 'SSH_SESSION_REMAINS_OPEN=%s\n' "$SSH_SESSION_REMAINS_OPEN"
      printf 'RETRY_DEFERRED_FOR_CONTROLLED_TEST=%s\n' "$RETRY_DEFERRED_FOR_CONTROLLED_TEST"
      printf 'CURRENT_MODE=%s\n' "$CURRENT_MODE"
      printf 'GIT_COMMIT=%s\n' "$GIT_COMMIT"
      printf 'GIT_TREE=%s\n' "$GIT_TREE"
      printf 'GIT_FILE_COUNT=%s\n' "$GIT_FILE_COUNT"
      printf 'SNAPSHOT_NAME=%s\n' "$SNAPSHOT_NAME"
      printf 'BACKUP_DIR=%s\n' "$BACKUP_DIR"
    } >"$tmp"
    chmod 600 "$tmp"
    mv -f "$tmp" "$out"
}

run_vm101_script() {
    local script
    local prepared
    local item
    local key
    local value
    script="$1"
    shift
    prepared="$(mktemp "$STEP_DIR/vm101-script.XXXXXX")"
    for item in "$@"; do
        key="${item%%=*}"
        value="${item#*=}"
        [[ "$key" =~ ^[A-Z0-9_]+$ ]] || { rm -f "$prepared"; return 91; }
        [[ "$value" != *"'"* ]] || { rm -f "$prepared"; return 92; }
        printf "export %s='%s'\n" "$key" "$value" >>"$prepared"
    done
    cat "$script" >>"$prepared"
    local rc
    "$SSH_BIN" -o BatchMode=yes pve-mgts "ssh -T -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'sh -s'" <"$prepared"
    rc=$?
    rm -f "$prepared"
    return "$rc"
}

copy_vm101_file() {
    local src
    local dst
    src="$1"
    dst="$2"
    [[ "$dst" =~ ^/tmp/[A-Za-z0-9._/-]+$ ]] || return 93
    "$SSH_BIN" -o BatchMode=yes pve-mgts "ssh -T -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'cat > $dst'" <"$src"
}

phase_begin() {
    CURRENT_PHASE="$1"
    router_step_phase_begin "$1" "${2:-none}"
    progress "$1"
}

phase_done() {
    router_step_phase_complete "$1" "${2:-complete}"
}

publish_object() {
    local label
    local expect
    local outvar
    local log
    label="$1"
    expect="$2"
    outvar="$3"
    shift 3
    log="$COMPONENTS/publish-${expect}.log"
    "$PUBLISHER" "$label" "$@" >"$log"
    router_publication_contract_load "$log" "$expect"
    "$HTTP" --url "$RPC_PUBLIC_URL" --output "$COMPONENTS/http-${expect}-index.html" >"$COMPONENTS/http-${expect}.log" 2>&1
    printf -v "$outvar" '%s' "$RPC_PUBLIC_URL"
}

preflight_object() {
    local label
    local expect
    local sample
    local classify
    local preflight
    label="$1"
    expect="$2"
    sample="$3"
    classify="$COMPONENTS/preflight-${expect}.classify"
    preflight="$COMPONENTS/preflight-${expect}.txt"
    "$PUBLISHER" --classify "$label" >"$classify"
    grep -Fqx "PUBLIC_OBJECT_KIND=$expect" "$classify"
    "$PUBLISHER" --preflight "$label" "$sample" >"$preflight"
    grep -qx 'RESULT=PASS_ROUTER_PUBLISH_PREFLIGHT' "$preflight"
}

rollback_pre_core() {
    [ "$BACKUP_READY" = true ] || return 0
    [ "$AUTO_ROLLBACK_ALLOWED" = true ] || return 0
    router_runtime_transition_rollback_allowed "$TRANSITION_FILE" || return 0
    progress automatic_pre_core_rollback
    run_vm101_script "$BUNDLE_DIR/scripts/vm101-rollback.sh" "R20F_BACKUP_DIR=$BACKUP_DIR" >"$COMPONENTS/automatic-rollback.log" 2>&1 || true
}

build_report_payload() {
    local mode
    local docs
    local html
    local safe
    local final_env
    mode="$1"
    docs="$STEP_DIR/${mode,,}-docs"
    html="$STEP_DIR/${mode,,}-html"
    safe="$STEP_DIR/${mode,,}-safe"
    final_env="$STEP_DIR/${mode,,}-runtime.env"
    write_final_env "$final_env"
    python3 "$BUNDLE_DIR/scripts/build_step_docs.py" --env "$final_env" --output-dir "$docs" --run-dir "$STEP_DIR" >"$COMPONENTS/${mode,,}-docs-build.log"
    python3 -m json.tool "$docs/facts.json" >/dev/null
    python3 "$HTML_BUILDER" --facts "$docs/facts.json" --verify "$docs/verify.txt" --rollback "$docs/rollback.sh" --output-dir "$html" --title-prefix R20F-R02 >"$COMPONENTS/${mode,,}-html.log"
    "$SAFE_BUILDER" "$safe" \
      "$STEP_FILE" step-code.sh \
      "$docs/report.txt" report.txt \
      "$docs/facts.json" facts.json \
      "$docs/verify.txt" verify.txt \
      "$docs/rollback.sh" rollback.sh \
      "$MAIN_LOG" main.log \
      "$PROGRESS_LOG" progress.log \
      "$TRANSFER" transfer-verify.txt \
      "$PHASE_CURRENT" phase-current.txt \
      "$PHASE_EVENTS" phase-events.log \
      "$COMPONENTS/production-contracts.txt" production-contracts.txt \
      "$COMPONENTS/bundle-gate.txt" bundle-gate.txt \
      "$COMPONENTS/vm101-preflight.txt" vm101-preflight.txt \
      "$COMPONENTS/snapshot.txt" snapshot.txt \
      "$COMPONENTS/vm101-backup.txt" vm101-backup.txt \
      "$COMPONENTS/vm101-apply.txt" vm101-apply.txt \
      "$COMPONENTS/vm101-postcheck.txt" vm101-postcheck.txt \
      "$COMPONENTS/vm101-git-publish.txt" vm101-git-publish.txt \
      "$COMPONENTS/router-machine-close-safe.txt" router-machine-close-safe.txt \
      "$COMPONENTS/vm130-source-export.txt" vm130-source-export.txt \
      "$COMPONENTS/final-http.log" final-http.txt \
      "$html/facts-public.html" facts-public.html \
      "$html/verify-public.html" verify-public.html \
      "$html/rollback-public.html" rollback-public.html >"$COMPONENTS/${mode,,}-safe-payload.log"
    printf '%s\n' "$safe"
}

publish_stop_report() {
    local safe
    local stop_label
    local out_env
    set +e
    safe="$(build_report_payload STOP 2>/dev/null)"
    stop_label="step050m07r20f_r02_${CURRENT_PHASE}_stop"
    out_env="$STEP_DIR/stop-finalize.env"
    if [ -d "$safe" ]; then
        "$FINALIZER" --label "$stop_label" --payload-dir "$safe" --workflow-current "$PHASE_CURRENT" --workflow-events "$PHASE_EVENTS" --output-env "$out_env" --expect-kind step-report >"$COMPONENTS/stop-finalize.log" 2>&1
        if [ -s "$out_env" ]; then
            STEP_REPORT_URL="$(field "$out_env" PUBLIC_URL)"
            FACTS_URL="${STEP_REPORT_URL}facts-public.html"
            VERIFY_URL="${STEP_REPORT_URL}verify-public.html"
            ROLLBACK_URL="${STEP_REPORT_URL}rollback-public.html"
            HTTP_VERIFY_PASS=true
            PUBLICATION_BARRIER=verified
        fi
    fi
    set -e
}

stop() {
    local stop_result
    local reason
    local rc
    stop_result="$1"
    reason="$2"
    rc="${3:-1}"
    trap - ERR
    if ! mkdir "$STOP_GUARD_DIR" 2>/dev/null; then
        exit "$rc"
    fi
    RESULT="$stop_result"
    STOP_REASON="$reason"
    if [ "$WORKFLOW_READY" = true ]; then
        router_step_phase_fail "$CURRENT_PHASE" "$reason" >/dev/null 2>&1 || true
    fi
    if [ "$CORE_CHANGE_COMPLETE" != true ]; then
        rollback_pre_core
    fi
    if [ "$WORKFLOW_READY" = true ] && ! router_step_publication_is_verified; then
        publish_stop_report || true
    fi
    emit_final
    exit "$rc"
}

on_err() {
    local line
    local rc
    line="$1"
    rc="$2"
    stop STOP_R20F_UNHANDLED_ERROR "phase=$CURRENT_PHASE line=$line rc=$rc" "$rc"
}

for required in "$WORKFLOW_LIB" "$CONTRACT_LIB" "$RUNTIME_TRANSITION_LIB" "$PUBLISHER" "$HTTP" "$FINALIZER" "$SAFE_BUILDER" "$HTML_BUILDER"; do
    [ -e "$required" ] || { RESULT=STOP_R20F_SHARED_API_MISSING; STOP_REASON="$required"; emit_final; exit 20; }
done

printf '%s
' 'RESULT=REUSED_R20C_VM130_PRODUCTION_CONTRACT_SNAPSHOT' >"$COMPONENTS/production-contracts.txt"

source "$WORKFLOW_LIB"
source "$CONTRACT_LIB"
source "$RUNTIME_TRANSITION_LIB"
router_step_workflow_init "$PHASE_CURRENT" "$PHASE_EVENTS" \
  publication_preflight vm101_baseline snapshot backup target_apply target_postcheck \
  machine_git machine_source_publication model_publication methods_publication \
  project_source_publication external_http_verification step_report_publication
router_runtime_transition_init "$TRANSITION_FILE"

# router-step-bootstrap has already verified ZIP, manifest, syntax, mandatory fixtures and R17/R19/R20 gates before invoking this installer.
actual_zip="$(sha256sum "$BUNDLE_COPY" | awk '{print $1}')"
actual_installer="$(sha256sum "$STEP_FILE" | awk '{print $1}')"
[ "$actual_zip" = "$EXPECTED_BUNDLE_SHA256" ] || { RESULT=STOP_COPY_OR_TRANSFER_ERROR; STOP_REASON=bundle_sha; emit_final; exit 20; }
[ "$actual_installer" = "$EXPECTED_INSTALLER_SHA256" ] || { RESULT=STOP_COPY_OR_TRANSFER_ERROR; STOP_REASON=installer_sha; emit_final; exit 20; }
printf '%s\n' 'RESULT=PASS_ROUTER_BUNDLE_GATE_R19' 'RESULT=PASS_ROUTER_BUNDLE_GATE_R20' 'RESULT=PASS_ROUTER_BUNDLE_GATE' 'SOURCE=router-step-bootstrap' >"$COMPONENTS/bundle-gate.txt"
COPY_VERIFY=PASS
router_runtime_transition_set "$TRANSITION_FILE" TRANSFER_VERIFIED true
printf 'COPY_VERIFY=PASS\nEXPECTED_BUNDLE_SHA256=%s\nACTUAL_BUNDLE_SHA256=%s\nEXPECTED_INSTALLER_SHA256=%s\nACTUAL_INSTALLER_SHA256=%s\nMANIFEST_VERIFY=PASS\nSYNTAX_VERIFY=PASS\nFIXTURE_VERIFY=PASS\nPREVIOUS_STEP_REPORT_URL=https://reports.secret-studio.ru/latest/20260720-150949_step050m07r20f_r01_vm101_baseline_stop/\nFIRST_UNFINISHED_PHASE=vm101_baseline\n' "$EXPECTED_BUNDLE_SHA256" "$actual_zip" "$EXPECTED_INSTALLER_SHA256" "$actual_installer" >"$TRANSFER"
WORKFLOW_READY=true
trap 'on_err "$LINENO" "$?"' ERR

phase_begin publication_preflight
[ "$(hostname)" = router-ops ] || stop STOP_R20F_WRONG_HOST "$(hostname)" 21
preflight_object "$MODEL_LABEL" vm101-model "$BUNDLE_DIR/project-sources/WG_PAID_MGTS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENING.md"
preflight_object "$METHODS_LABEL" vm101-methods "$BUNDLE_DIR/project-sources/WG_PAID_MGTS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENING.md"
preflight_object "$PROJECT_LABEL" project-source-post "$BUNDLE_DIR/project-sources/WG_PAID_MGTS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENING.md"
preflight_object "$STEP_LABEL" step-report "$BUNDLE_DIR/README.md"
phase_done publication_preflight

phase_begin vm101_baseline
copy_vm101_file "$BUNDLE_DIR/baseline-manifest.sha256" /tmp/r20f-baseline-manifest.sha256
# A baseline mismatch is an expected classified STOP, not an unhandled shell error.
# Commands used as an if-condition are excluded from ERR-trap propagation.
if run_vm101_script "$BUNDLE_DIR/scripts/vm101-preflight.sh" 'R20F_BASELINE_MANIFEST=/tmp/r20f-baseline-manifest.sha256'  | tee "$COMPONENTS/vm101-preflight.txt"; then
    vm101_preflight_rc=0
else
    vm101_preflight_rc=${PIPESTATUS[0]}
fi
if [ "$vm101_preflight_rc" -ne 0 ]; then
    remote_result="$(awk -F= '$1=="RESULT" && $2 ~ /^STOP_/{v=$2} END{print v}' "$COMPONENTS/vm101-preflight.txt")"
    stop "${remote_result:-STOP_R20F_BASELINE_REMOTE_FAILED}" preflight "$vm101_preflight_rc"
fi
grep -qx 'RESULT=PASS_R20F_VM101_BASELINE' "$COMPONENTS/vm101-preflight.txt" || stop STOP_R20F_BASELINE_NOT_PROVEN preflight 22
router_runtime_transition_set "$TRANSITION_FILE" PREFLIGHT_COMPLETE true
phase_done vm101_baseline

phase_begin snapshot
test "${#SNAPSHOT_NAME}" -le 40 || stop STOP_R20F_SNAPSHOT_NAME_TOO_LONG "$SNAPSHOT_NAME" 23
[ "${#SNAPSHOT_NAME}" -le 32 ] || stop STOP_R20F_SNAPSHOT_NAME_NOT_PREFERRED "$SNAPSHOT_NAME" 23
"$SSH_BIN" -o BatchMode=yes pve-mgts "qm listsnapshot 101 | grep -F -- '$SNAPSHOT_NAME' >/dev/null && exit 9 || qm snapshot 101 '$SNAPSHOT_NAME' --description '$STEP_ID pre-core'" | tee "$COMPONENTS/snapshot.txt"
phase_done snapshot

progress transfer_exact_target_payload
copy_vm101_file "$BUNDLE_DIR/target-manifest.sha256" /tmp/r20f-target-manifest.sha256
"$SSH_BIN" -o BatchMode=yes pve-mgts "ssh -T -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'rm -rf $REMOTE_STAGE; mkdir -p $REMOTE_STAGE/rootfs; tar -xzf - -C $REMOTE_STAGE/rootfs'" < <(tar -czf - -C "$BUNDLE_DIR/payload/rootfs" .)

phase_begin backup
if run_vm101_script "$BUNDLE_DIR/scripts/vm101-apply.sh" "R20F_STAGE_DIR=$REMOTE_STAGE/rootfs" "R20F_BACKUP_DIR=$BACKUP_DIR" 'R20F_TARGET_MANIFEST=/tmp/r20f-target-manifest.sha256' | tee "$COMPONENTS/vm101-transaction.txt"; then
    transaction_rc=0
else
    transaction_rc=${PIPESTATUS[0]}
fi
cp -a "$COMPONENTS/vm101-transaction.txt" "$COMPONENTS/vm101-backup.txt"
cp -a "$COMPONENTS/vm101-transaction.txt" "$COMPONENTS/vm101-apply.txt"
cp -a "$COMPONENTS/vm101-transaction.txt" "$COMPONENTS/vm101-postcheck.txt"
if [ "$transaction_rc" -ne 0 ]; then
    remote_result="$(awk -F= '$1=="RESULT" && $2 ~ /^STOP_/{v=$2} END{print v}' "$COMPONENTS/vm101-transaction.txt")"
    stop "${remote_result:-STOP_R20F_TRANSACTION_REMOTE_FAILED}" transaction "$transaction_rc"
fi
grep -qx 'RESULT=PASS_R20F_BACKUP_READY' "$COMPONENTS/vm101-transaction.txt" || stop STOP_R20F_BACKUP_NOT_READY transaction 24
grep -qx 'RESULT=PASS_R20F_VM101_TARGET_APPLIED' "$COMPONENTS/vm101-transaction.txt" || stop STOP_R20F_TARGET_APPLY_FAILED transaction 25
grep -qx 'RESULT=PASS_R20F_VM101_TARGET_POSTCHECK' "$COMPONENTS/vm101-transaction.txt" || stop STOP_R20F_TARGET_POSTCHECK_FAILED transaction 26
grep -qx 'CORE_CHANGE_COMPLETE=true' "$COMPONENTS/vm101-transaction.txt" || stop STOP_R20F_CORE_BOUNDARY_NOT_PROVEN transaction 26
BACKUP_READY=true
CURRENT_MODE="$(field "$COMPONENTS/vm101-transaction.txt" CURRENT_MODE)"
[ -n "$CURRENT_MODE" ] || CURRENT_MODE=unknown
RETRY_DEFERRED_FOR_CONTROLLED_TEST="$(field "$COMPONENTS/vm101-transaction.txt" RETRY_DEFERRED_FOR_CONTROLLED_TEST)"
[ -n "$RETRY_DEFERRED_FOR_CONTROLLED_TEST" ] || RETRY_DEFERRED_FOR_CONTROLLED_TEST=false
CORE_CHANGE_COMPLETE=true
AUTO_ROLLBACK_ALLOWED=false
router_runtime_transition_set "$TRANSITION_FILE" BACKUP_READY true
router_runtime_transition_set "$TRANSITION_FILE" FILES_INSTALLED true
router_runtime_transition_set "$TRANSITION_FILE" CORE_CHANGE_COMPLETE true
router_runtime_transition_set "$TRANSITION_FILE" ACTIVATION_COMPLETE true
phase_done backup

phase_begin target_apply
phase_done target_apply

phase_begin target_postcheck
phase_done target_postcheck

phase_begin machine_git
"$SSH_BIN" -o BatchMode=yes pve-mgts "ssh -T -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 '/usr/local/sbin/router-vm101-git-publish.sh --publish \"$STEP_ID\"'" | tee "$COMPONENTS/vm101-git-publish.txt"
grep -qx 'RESULT=PASS_vm101_GIT_PUBLISH' "$COMPONENTS/vm101-git-publish.txt" || stop STOP_R20F_MACHINE_GIT_PUBLISH_FAILED machine_git 27
GIT_COMMIT="$(field "$COMPONENTS/vm101-git-publish.txt" GIT_COMMIT)"
GIT_TREE="$(field "$COMPONENTS/vm101-git-publish.txt" GIT_TREE)"
GIT_FILE_COUNT="$(field "$COMPONENTS/vm101-git-publish.txt" GIT_FILE_COUNT)"
[[ "$GIT_COMMIT" =~ ^[0-9a-f]{40}$ ]] || stop STOP_R20F_MACHINE_GIT_COMMIT "$GIT_COMMIT" 27
[[ "$GIT_TREE" =~ ^[0-9a-f]{40}$ ]] || stop STOP_R20F_MACHINE_GIT_TREE "$GIT_TREE" 27
[ "$GIT_FILE_COUNT" = 37 ] || stop STOP_R20F_MACHINE_GIT_COUNT "$GIT_FILE_COUNT" 27
phase_done machine_git

phase_begin machine_source_publication
"$BASE/bin/router-machine-close-safe" vm101 "$STEP_ID" | tee "$COMPONENTS/router-machine-close-safe.txt"
grep -qx 'RESULT=PASS_ROUTER_MACHINE_CLOSE' "$COMPONENTS/router-machine-close-safe.txt" || stop STOP_R20F_MACHINE_CLOSE_FAILED marker 28
[ "$(field "$COMPONENTS/router-machine-close-safe.txt" COMMIT)" = "$GIT_COMMIT" ] || stop STOP_R20F_MACHINE_CLOSE_COMMIT mismatch 28
[ "$(field "$COMPONENTS/router-machine-close-safe.txt" TREE)" = "$GIT_TREE" ] || stop STOP_R20F_MACHINE_CLOSE_TREE mismatch 28
[ "$(field "$COMPONENTS/router-machine-close-safe.txt" GIT_FILE_COUNT)" = "$GIT_FILE_COUNT" ] || stop STOP_R20F_MACHINE_CLOSE_COUNT mismatch 28
VM101_PUBLIC_URL="$(field "$COMPONENTS/router-machine-close-safe.txt" VM101_PUBLIC_URL)"
[[ "$VM101_PUBLIC_URL" == https://reports.secret-studio.ru/latest/*/ ]] || stop STOP_R20F_MACHINE_CLOSE_URL "$VM101_PUBLIC_URL" 28
phase_done machine_source_publication

printf '%s
' 'RESULT=REUSED_PREVIOUS_VM130_SOURCE' "VM130_SOURCE_URL=$VM130_SOURCE_URL" >"$COMPONENTS/vm130-source-export.txt"

progress vm101_safe_artifact_export
run_vm101_script "$BUNDLE_DIR/scripts/vm101-export-artifacts.sh" >"$STEP_DIR/vm101-artifacts.tar.gz"
tar -tzf "$STEP_DIR/vm101-artifacts.tar.gz" >"$COMPONENTS/vm101-artifacts-list.txt"
ARTIFACT_DIR="$STEP_DIR/vm101-artifacts"
mkdir -p "$ARTIFACT_DIR"
tar -xzf "$STEP_DIR/vm101-artifacts.tar.gz" -C "$ARTIFACT_DIR"

VM101_MODEL_URL="$PUBLIC_BASE/latest/${PUBLISH_TS}_${MODEL_LABEL}/"
VM101_METHODS_URL="$PUBLIC_BASE/latest/${PUBLISH_TS}_${METHODS_LABEL}/"
PROJECT_SOURCE_POST_URL="$PUBLIC_BASE/latest/${PUBLISH_TS}_${PROJECT_LABEL}/"
PROJECT_SOURCE_POST_FILE_URL="${PROJECT_SOURCE_POST_URL}WG_PAID_MGTS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENING.md"
STEP_REPORT_URL="$PUBLIC_BASE/latest/${PUBLISH_TS}_${STEP_LABEL}/"
RUNTIME_ENV="$STEP_DIR/runtime-publications.env"
write_final_env "$RUNTIME_ENV"
RUNTIME_DOCS="$STEP_DIR/runtime-publications"
python3 "$BUNDLE_DIR/scripts/build_runtime_publications.py" --env "$RUNTIME_ENV" --output-dir "$RUNTIME_DOCS" --contracts-manifest "$BUNDLE_DIR/reference/vm130-required-contracts.sha256" | tee "$COMPONENTS/runtime-publications-build.txt"

phase_begin model_publication
MODEL_SAFE="$STEP_DIR/model-safe"
"$SAFE_BUILDER" "$MODEL_SAFE" \
  "$RUNTIME_DOCS/model-summary.txt" model-summary.txt \
  "$ARTIFACT_DIR/architecture-status.txt" architecture-status.txt \
  "$ARTIFACT_DIR/machine-git-check.txt" machine-git-check.txt \
  "$ARTIFACT_DIR/retry-service.txt" retry-service.txt \
  "$ARTIFACT_DIR/runtime-state.kv" runtime-state.txt \
  "$ARTIFACT_DIR/durable-state.kv" durable-state.txt \
  "$ARTIFACT_DIR/durable-quarantine.tsv" durable-quarantine.txt \
  "$ARTIFACT_DIR/durable-events.tsv" durable-events.txt \
  "$ARTIFACT_DIR/retry-log-tail.txt" retry-log-tail.txt >"$COMPONENTS/model-safe-payload.txt"
actual_model=''
publish_object "$MODEL_LABEL" vm101-model actual_model "$MODEL_SAFE"/*
[ "$actual_model" = "$VM101_MODEL_URL" ] || stop STOP_R20F_MODEL_URL_MISMATCH "$actual_model" 30
phase_done model_publication

phase_begin methods_publication
METHODS_SAFE="$STEP_DIR/methods-safe"
"$SAFE_BUILDER" "$METHODS_SAFE" \
  "$RUNTIME_DOCS/methods-summary.txt" methods-summary.txt \
  "$RUNTIME_DOCS/WG_PAID_MGTS_VM130_SHARED_WORKFLOW_CONTRACT_SNAPSHOT_AFTER_R20C.md" vm130-contracts.txt \
  "$BUNDLE_DIR/reference/production-contract-origin.txt" contract-origin.txt >"$COMPONENTS/methods-safe-payload.txt"
actual_methods=''
publish_object "$METHODS_LABEL" vm101-methods actual_methods "$METHODS_SAFE"/*
[ "$actual_methods" = "$VM101_METHODS_URL" ] || stop STOP_R20F_METHODS_URL_MISMATCH "$actual_methods" 31
phase_done methods_publication

phase_begin project_source_publication
PS_FILES=(
  "$BUNDLE_DIR/project-sources/WG_PAID_MGTS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENING.md"
  "$RUNTIME_DOCS/WG_PAID_MGTS_CHECKPOINT_AFTER_R20F_BEFORE_R20E_R03.md"
  "$RUNTIME_DOCS/WG_PAID_MGTS_VM130_SHARED_WORKFLOW_CONTRACT_SNAPSHOT_AFTER_R20C.md"
)
actual_project=''
publish_object "$PROJECT_LABEL" project-source-post actual_project "${PS_FILES[@]}"
[ "$actual_project" = "$PROJECT_SOURCE_POST_URL" ] || stop STOP_R20F_PROJECT_SOURCE_URL_MISMATCH "$actual_project" 32
phase_done project_source_publication

phase_begin external_http_verification
: >"$COMPONENTS/final-http.log"
for url in "$VM101_PUBLIC_URL" "$VM130_SOURCE_URL" "$VM101_MODEL_URL" "$VM101_METHODS_URL" "$PROJECT_SOURCE_POST_URL" "$LOCAL_M07_PLAN_URL" "$GLOBAL_PROJECT_PLAN_URL" "$ACCESS_MAP_URL" "$VM100_PUBLIC_URL" "$VM121_PUBLIC_URL"; do
    "$HTTP" --url "$url" --output "$STEP_DIR/http-final-$(printf '%s' "$url" | sha256sum | cut -c1-12).html" >>"$COMPONENTS/final-http.log" 2>&1
 done
HTTP_VERIFY_PASS=true
phase_done external_http_verification

phase_begin step_report_publication
RESULT=PASS_R20F_LONG_RUNNING_REFRESH_CLOCK_HARDENED_R02
STOP_REASON=none
PUBLICATION_BARRIER=verified
PASS_SAFE="$(build_report_payload PASS)"
FINAL_ENV="$STEP_DIR/finalize.env"
"$FINALIZER" --label "$STEP_LABEL" --payload-dir "$PASS_SAFE" --workflow-current "$PHASE_CURRENT" --workflow-events "$PHASE_EVENTS" --output-env "$FINAL_ENV" --expect-kind step-report >"$COMPONENTS/finalize.log"
actual_step="$(field "$FINAL_ENV" PUBLIC_URL)"
[ "$actual_step" = "$STEP_REPORT_URL" ] || stop STOP_R20F_STEP_REPORT_URL_MISMATCH "$actual_step" 33
PREVIOUS_MOVED_COUNT="$(field "$FINAL_ENV.publish" PREVIOUS_MOVED_COUNT)"
[ -n "$PREVIOUS_MOVED_COUNT" ] || PREVIOUS_MOVED_COUNT=0
FACTS_URL="${STEP_REPORT_URL}facts-public.html"
VERIFY_URL="${STEP_REPORT_URL}verify-public.html"
ROLLBACK_URL="${STEP_REPORT_URL}rollback-public.html"
PUBLICATION_BARRIER=verified
HTTP_VERIFY_PASS=true
trap - ERR
emit_final
exit 0
