#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
BASE="${ROUTER_OPS_BASE:-/opt/router-ops}"
ROOT="${BUNDLE_ROOT:?}"
RUN_DIR="${ROUTER_DETACHED_RUN_DIR:?}"
CHILD_RESULT="${ROUTER_DETACHED_CHILD_RESULT:?}"
INCOMING="${ROUTER_STEP_INCOMING:-/home/ops/incoming}"
SELFTEST="${ROUTER_EXACT_WORKER_SELFTEST:-false}"

CASE=pass
if [[ "$SELFTEST" == true ]]; then
  case "${ROUTER_PUBLIC_ROOT:-}" in
    */fail-source/public) CASE=fail-source ;;
    */fail-apply/public) CASE=fail-apply ;;
  esac
fi

STEP=STEP_050M07P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY_CONTINUATION
VM100_COMMIT=8c5d11b7e4b119757ea16b46775b26e0ac903d7c
VM100_TREE=f25aab0f1886647b52a11ccebe080894bd06542a
VM100_COUNT=34
VM101_COMMIT=94a1c5627bacf9212d3fb2af1a77507ec57ff74b
VM101_TREE=ee4dddf35e308096d6496a4ecc25268ebcb3058a
VM101_COUNT=59
VM121_BASE_COMMIT=e3409bee5b1466839a7293af6ead97e515ca8f20
VM121_BASE_TREE=7ace7d88b02a457f91469394c6f1f8bdf0c528b5
VM121_BASE_COUNT=47
VM121_EXPECTED_TREE=379575e11661f93db2a4214974cc53aee7828653
VM121_EXPECTED_COUNT=48
VM100_PUBLIC_URL=https://reports.secret-studio.ru/latest/20260816-094040_vm100_git_source_8c5d11b7e4b1/
VM101_PUBLIC_URL=https://reports.secret-studio.ru/latest/20260816-094047_vm101_git_source_94a1c5627bac/

CURRENT="$RUN_DIR/workflow-current.txt"
EVENTS="$RUN_DIR/workflow-events.tsv"
EVIDENCE="$RUN_DIR/evidence"
REPORT="$RUN_DIR/report"
PAYLOAD="$RUN_DIR/public-payload"
FINAL_ENV="$RUN_DIR/final-publication.env"
TARGET_DIR="$RUN_DIR/target"
mkdir -p "$EVIDENCE" "$REPORT" "$PAYLOAD" "$TARGET_DIR" "$INCOMING"
chmod 700 "$EVIDENCE" "$REPORT" "$PAYLOAD" "$TARGET_DIR"

source "$BASE/lib/router-step-workflow.sh"
source <("$BASE/bin/router-release-contract" env --root "$ROOT")
router_step_workflow_init "$CURRENT" "$EVENTS" preflight apply machine_close postcheck report_publish archive

CORE_CHANGE_COMPLETE=false
CORE_CHANGE_REPEATED=false
SOURCE_CHANGED=false
LIVE_DATABASE_WRITTEN=false
DATABASE_SCHEMA_CHANGED=false
SOURCE_ROLLBACK_STATUS=not_required
DATABASE_ROLLBACK_STATUS=not_required
BACKEND_RECOVERY_STATUS=not_required
RUNTIME_PROVISIONING_ACTIVE=false
EXTERNAL_ONBOARDING_ACTIVE=false
STOP_DETAIL=unknown
STOP_HANDLED=false
STEP_REPORT_URL=unknown
LATEST_ARCHIVE=not_created
LATEST_ARCHIVE_SHA256=unknown
VM121_NEW_COMMIT=unknown
VM121_NEW_TREE=unknown
VM121_NEW_FILE_COUNT=unknown
VM121_PUBLIC_URL=unknown
REMOTE_STAGE=unknown
REMOTE_PKG=unknown
BACKUP_DIR=unknown

last_field(){ local k="$1" f="$2"; awk -F= -v k="$k" '$1==k{v=substr($0,index($0,"=")+1)} END{print v}' "$f"; }
write_child(){
  local result="$1" rc="$2" tmp="${CHILD_RESULT}.tmp.$$"
  {
    echo RESULT="$result"; echo WORKER_RC="$rc"; echo CORE_CHANGE_COMPLETE="$CORE_CHANGE_COMPLETE"; echo CORE_CHANGE_REPEATED=false
    echo SOURCE_CHANGED="$SOURCE_CHANGED"; echo LIVE_DATABASE_WRITTEN="$LIVE_DATABASE_WRITTEN"; echo DATABASE_SCHEMA_CHANGED="$DATABASE_SCHEMA_CHANGED"
    echo SOURCE_ROLLBACK_STATUS="$SOURCE_ROLLBACK_STATUS"; echo DATABASE_ROLLBACK_STATUS="$DATABASE_ROLLBACK_STATUS"; echo BACKEND_RECOVERY_STATUS="$BACKEND_RECOVERY_STATUS"
    echo RUNTIME_PROVISIONING_ACTIVE=false; echo EXTERNAL_ONBOARDING_ACTIVE=false; echo STOP_DETAIL="$STOP_DETAIL"; echo BACKUP_DIR="$BACKUP_DIR"
    echo VM100_COMMIT="$VM100_COMMIT"; echo VM100_TREE="$VM100_TREE"; echo VM100_FILE_COUNT="$VM100_COUNT"; echo VM100_PUBLIC_URL="$VM100_PUBLIC_URL"
    echo VM101_COMMIT="$VM101_COMMIT"; echo VM101_TREE="$VM101_TREE"; echo VM101_FILE_COUNT="$VM101_COUNT"; echo VM101_PUBLIC_URL="$VM101_PUBLIC_URL"
    echo VM121_COMMIT="$VM121_NEW_COMMIT"; echo VM121_TREE="$VM121_NEW_TREE"; echo VM121_FILE_COUNT="$VM121_NEW_FILE_COUNT"; echo VM121_PUBLIC_URL="$VM121_PUBLIC_URL"
    echo STEP_REPORT_URL="$STEP_REPORT_URL"; echo LATEST_ARCHIVE="$LATEST_ARCHIVE"; echo LATEST_ARCHIVE_SHA256="$LATEST_ARCHIVE_SHA256"
  } > "$tmp"; chmod 600 "$tmp"; mv "$tmp" "$CHILD_RESULT"
}
archive_latest(){
  local log="$EVIDENCE/archive.log"
  router_step_archive_latest_python "$BASE" "$INCOMING" "$(date -u +%Y%m%d-%H%M%S)" | tee "$log"
  LATEST_ARCHIVE="$(last_field LATEST_ARCHIVE "$log")"; LATEST_ARCHIVE_SHA256="$(last_field LATEST_ARCHIVE_SHA256 "$log")"
}
cleanup_remote(){
  [[ "$SELFTEST" == false && "$REMOTE_STAGE" != unknown ]] || return 0
  set +e; ssh -T -o BatchMode=yes -o ConnectTimeout=20 vm121 "rm -rf '$REMOTE_STAGE' '$REMOTE_PKG'" >/dev/null 2>&1; set -e
}
write_stop_report(){
  local rc="$1" line="$2" cmd="$3"
  cat > "$REPORT/report.txt" <<EOR
RESULT=STOP_P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY
REVISION=R10
STOP_RC=$rc
STOP_LINE=$line
STOP_DETAIL=$STOP_DETAIL
CORE_CHANGE_COMPLETE=$CORE_CHANGE_COMPLETE
CORE_CHANGE_REPEATED=false
SOURCE_CHANGED=$SOURCE_CHANGED
LIVE_DATABASE_WRITTEN=$LIVE_DATABASE_WRITTEN
DATABASE_SCHEMA_CHANGED=$DATABASE_SCHEMA_CHANGED
SOURCE_ROLLBACK_STATUS=$SOURCE_ROLLBACK_STATUS
DATABASE_ROLLBACK_STATUS=$DATABASE_ROLLBACK_STATUS
BACKEND_RECOVERY_STATUS=$BACKEND_RECOVERY_STATUS
RUNTIME_PROVISIONING_ACTIVE=false
EXTERNAL_ONBOARDING_ACTIVE=false
VM100_COMMIT=$VM100_COMMIT
VM100_TREE=$VM100_TREE
VM101_COMMIT=$VM101_COMMIT
VM101_TREE=$VM101_TREE
VM121_BASE_COMMIT=$VM121_BASE_COMMIT
VM121_BASE_TREE=$VM121_BASE_TREE
VM121_EXPECTED_TREE=$VM121_EXPECTED_TREE
BACKUP_DIR=$BACKUP_DIR
EOR
  printf 'STOP_COMMAND=%q\n' "$cmd" >> "$REPORT/report.txt"
  cp "$REPORT/report.txt" "$REPORT/verify.txt"; cp "$ROOT/scripts/run-step.sh" "$REPORT/executed-step.sh"; cp "$ROOT/release-info.json" "$REPORT/release-info.json"; cp "$ROOT/rollback/README.md" "$REPORT/rollback.txt"
  for f in pre-vm100-source.txt pre-vm101-source.txt pre-vm121-source.txt pre-vm100-source-validation.txt pre-vm101-source-validation.txt pre-vm121-source-validation.txt apply.txt apply-validation.txt machine-close.txt post-live.txt; do [[ ! -f "$EVIDENCE/$f" ]] || cp "$EVIDENCE/$f" "$REPORT/$f"; done
}
stop_handler(){
  local rc="$1" line="$2" cmd="$3"; trap - ERR
  [[ "$STOP_HANDLED" == false ]] || return "$rc"; STOP_HANDLED=true; cleanup_remote; write_stop_report "$rc" "$line" "$cmd"
  set +e
  if [[ "$SELFTEST" == true ]]; then
    DEST="${ROUTER_PUBLIC_ROOT:?}/latest/p24-r10-$CASE-selftest"; rm -rf "$DEST"; mkdir -p "$DEST"; cp -a "$REPORT"/. "$DEST"/; STEP_REPORT_URL="selftest://p24-r10-$CASE/"; archive_latest >/dev/null 2>&1
  else
    args=(); while IFS= read -r f; do args+=("$f" "$(basename "$f")"); done < <(find "$REPORT" -maxdepth 1 -type f -print | LC_ALL=C sort)
    router_step_publish_payload step050m07p24_r10_durable_profile_provisioning_boundary_continuation_stop "$REPORT" "$PAYLOAD" "$CURRENT" "$EVENTS" "$FINAL_ENV" "${args[@]}" >/dev/null 2>&1 || true
    [[ -f "$FINAL_ENV" ]] && STEP_REPORT_URL="$(last_field PUBLIC_URL "$FINAL_ENV")"; archive_latest >/dev/null 2>&1
  fi
  set -e; write_child STOP_P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY "$rc"; return "$rc"
}
trap 'rc=$?; stop_handler "$rc" "$LINENO" "$BASH_COMMAND"; exit "$rc"' ERR

self_source(){
  local machine="$1" head="$2" tree="$3" count="$4" staged="${5:-0}"
  cat <<EOS
MODE=--check
MACHINE_ID=$machine
LOCAL_HEAD=$head
REMOTE_HEAD=$head
STAGED_CHANGE_COUNT=$staged
SIMULATED_TREE_SHA=$tree
SIMULATED_TREE_FILE_COUNT=$count
RESULT=PASS_${machine^^}_GIT_PUBLISH_CHECK
GIT_COMMIT=$head
GIT_TREE=$tree
GIT_FILE_COUNT=$count
COMMIT_CREATED=false
PUSH_PERFORMED=false
EOS
}
self_apply(){
  cat <<'EOS'
ALEMBIC_VERSION=0004_profile_provisioning_boundary
BUSINESS_ROWS_BEFORE=0
BUSINESS_ROWS_AFTER=0
BACKUP_READY=true
BACKUP_DIR=/root/router-ops-backups/p24-r10-selftest
ENCRYPTED_BACKUP_PRESENT=true
BACKUP_RESTORE_PROOF=PASS
RESTORED_MIGRATION_PROOF=PASS
CLEAN_INSTALL_MIGRATION_PROOF=PASS
ALLOCATOR_CONCURRENCY_UNIQUE=PASS
LEGACY_COLLISION_AVOIDANCE=PASS
CREDENTIAL_TRANSACTION=PASS
SAFE_JOB_PAYLOAD=PASS
DISABLE_RESERVATION_HELD_UNTIL_ACK=PASS
REUSE_AFTER_CONFIRMED_DISABLE=PASS
RETRY_BACKOFF_RESERVATION=PASS
EXISTING_VM100_LIFECYCLE_ADAPTER_REUSED=true
AGENT_DIRECT_RUNTIME_WRITE_PRESENT=false
AGENT_PATH_ACTIVE=inactive
AGENT_PATH_ENABLED=disabled
AGENT_TIMER_ACTIVE=inactive
AGENT_TIMER_ENABLED=disabled
AGENT_SERVICE_ACTIVE=inactive
CORE_SOURCE_CHANGE_COMPLETE=true
SOURCE_CHANGED=true
SOURCE_ROLLBACK_STATUS=not_required
DATABASE_ROLLBACK_STATUS=not_required
BACKEND_RECOVERY_STATUS=PASS
LIVE_DATABASE_WRITTEN=true
DATABASE_SCHEMA_CHANGED=true
RUNTIME_PROVISIONING_ACTIVE=false
EXTERNAL_ONBOARDING_ACTIVE=false
RESULT=PASS_P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY
EOS
}
self_close(){
  cat <<EOS
RESULT=PASS_VM121_GIT_PUBLISH
MACHINE=vm121
COMMIT=1111111111111111111111111111111111111111
TREE=$VM121_EXPECTED_TREE
GIT_FILE_COUNT=$VM121_EXPECTED_COUNT
VM121_PUBLIC_URL=https://reports.example/latest/vm121/
RESULT=PASS_ROUTER_MACHINE_CLOSE
EOS
}
self_post_live(){
cat <<'EOS'
ALEMBIC_VERSION=0004_profile_provisioning_boundary
BUSINESS_ROWS=0
CONNECTION_PROFILE_ROWS=0
PEER_CREDENTIAL_ROWS=0
PROVISIONING_JOB_ROWS=0
TUNNEL_IP_COLUMN_COUNT=3
TUNNEL_IP_UNIQUE_INDEX_COUNT=1
AGENT_PATH_ACTIVE=inactive
AGENT_PATH_ENABLED=disabled
AGENT_TIMER_ACTIVE=inactive
AGENT_TIMER_ENABLED=disabled
AGENT_SERVICE_ACTIVE=inactive
RUNTIME_PROVISIONING_ACTIVE=false
EXTERNAL_ONBOARDING_ACTIVE=false
RESULT=PASS_P24_R10_POST_LIVE
EOS
}

router_step_phase_begin preflight
if [[ "$SELFTEST" == true ]]; then
  self_source vm100 "$VM100_COMMIT" "$VM100_TREE" "$VM100_COUNT" > "$EVIDENCE/pre-vm100-source.txt"
  self_source vm101 "$VM101_COMMIT" "$VM101_TREE" "$VM101_COUNT" > "$EVIDENCE/pre-vm101-source.txt"
  self_source vm121 "$VM121_BASE_COMMIT" "$VM121_BASE_TREE" "$VM121_BASE_COUNT" > "$EVIDENCE/pre-vm121-source.txt"
  [[ "$CASE" != fail-source ]] || sed -i 's/STAGED_CHANGE_COUNT=0/STAGED_CHANGE_COUNT=1/' "$EVIDENCE/pre-vm121-source.txt"
else
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 vm121 /usr/local/sbin/router-vm121-git-publish.sh --check > "$EVIDENCE/pre-vm121-source.txt" 2>&1
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 pve-mgts "ssh -n -o BatchMode=yes -o ConnectTimeout=10 -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.1 /usr/local/sbin/router-vm100-git-publish.sh --check" > "$EVIDENCE/pre-vm100-source.txt" 2>&1
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 pve-mgts "ssh -n -o BatchMode=yes -o ConnectTimeout=10 -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 /usr/local/sbin/router-vm101-git-publish.sh --check" > "$EVIDENCE/pre-vm101-source.txt" 2>&1
fi
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/pre-vm100-source.txt" vm100 "$VM100_COMMIT" "$VM100_TREE" "$VM100_COUNT" 0 > "$EVIDENCE/pre-vm100-source-validation.txt" || { STOP_DETAIL=pre_vm100_source; false; }
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/pre-vm101-source.txt" vm101 "$VM101_COMMIT" "$VM101_TREE" "$VM101_COUNT" 0 > "$EVIDENCE/pre-vm101-source-validation.txt" || { STOP_DETAIL=pre_vm101_source; false; }
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/pre-vm121-source.txt" vm121 "$VM121_BASE_COMMIT" "$VM121_BASE_TREE" "$VM121_BASE_COUNT" 0 > "$EVIDENCE/pre-vm121-source-validation.txt" || { STOP_DETAIL=pre_vm121_source; false; }

if [[ "$SELFTEST" == false ]]; then
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 pve-mgts "ssh -o BatchMode=yes -o ConnectTimeout=10 -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.1 'if [ -x /usr/local/sbin/router-wgpay-peer-lifecycle ]; then /usr/local/sbin/router-wgpay-peer-lifecycle --status; else /usr/local/sbin/router-wgpay-peer-lifecycle.sh --status; fi'" > "$EVIDENCE/vm100-lifecycle.txt" 2>&1
  grep -Fq 'RESULT=PASS_PEER_LIFECYCLE_STATUS' "$EVIDENCE/vm100-lifecycle.txt" || { STOP_DETAIL=vm100_lifecycle; false; }
  grep -Fq 'registry_valid=true' "$EVIDENCE/vm100-lifecycle.txt" || { STOP_DETAIL=vm100_lifecycle_registry; false; }
  grep -Fq 'selector_registry_consistent=true' "$EVIDENCE/vm100-lifecycle.txt" || { STOP_DETAIL=vm100_lifecycle_selector; false; }
fi
PKG="$ROOT/$ROUTER_RELEASE_TARGET_PACKAGE_PATH"
"$ROOT/scripts/target-apply.sh" "$ROUTER_RELEASE_TARGET_PACKAGE_SHA256" "$PKG" "$TARGET_DIR" > "$EVIDENCE/target-extract.txt"
router_step_phase_complete preflight exact_post_beach_sources_lifecycle_and_target_verified

router_step_phase_begin apply
target_rc=0
if [[ "$SELFTEST" == true ]]; then
  self_apply > "$EVIDENCE/apply.txt"
  if [[ "$CASE" == fail-apply ]]; then
    sed -i \
      -e 's/CORE_SOURCE_CHANGE_COMPLETE=true/CORE_SOURCE_CHANGE_COMPLETE=false/' \
      -e 's/SOURCE_ROLLBACK_STATUS=not_required/SOURCE_ROLLBACK_STATUS=PASS/' \
      -e 's/DATABASE_ROLLBACK_STATUS=not_required/DATABASE_ROLLBACK_STATUS=PASS/' \
      -e 's/RESULT=PASS_P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY/RESULT=STOP_P24_R10_DURABLE_PROFILE_PROVISIONING_BOUNDARY/' \
      "$EVIDENCE/apply.txt"
    target_rc=1
  fi
else
  token="$(basename "$RUN_DIR" | tr -cd 'A-Za-z0-9._-')"
  REMOTE_STAGE="/root/router-step-p24-r10-$token"; REMOTE_PKG="/root/router-step-p24-r10-$token.tar.gz"
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 vm121 "umask 077; cat > '$REMOTE_PKG'" < "$PKG" || { STOP_DETAIL=remote_package_transfer; false; }
  ssh -T -o BatchMode=yes -o ConnectTimeout=20 vm121 "rm -rf '$REMOTE_STAGE'; install -d -m 0700 '$REMOTE_STAGE'; tar -xzf '$REMOTE_PKG' -C '$REMOTE_STAGE'" > "$EVIDENCE/remote-stage.txt" 2>&1 || { STOP_DETAIL=remote_package_extract; false; }
  if ssh -T -o BatchMode=yes -o ConnectTimeout=20 vm121 "/bin/bash '$REMOTE_STAGE/vm121-p24-r10-apply.sh' '$REMOTE_STAGE/candidate'" > "$EVIDENCE/apply.txt" 2>&1; then target_rc=0; else target_rc=$?; fi
fi
CORE_CHANGE_COMPLETE="$(last_field CORE_SOURCE_CHANGE_COMPLETE "$EVIDENCE/apply.txt")"; [[ "$CORE_CHANGE_COMPLETE" == true || "$CORE_CHANGE_COMPLETE" == false ]] || CORE_CHANGE_COMPLETE=false
SOURCE_CHANGED="$(last_field SOURCE_CHANGED "$EVIDENCE/apply.txt")"; [[ "$SOURCE_CHANGED" == true || "$SOURCE_CHANGED" == false ]] || SOURCE_CHANGED=false
LIVE_DATABASE_WRITTEN="$(last_field LIVE_DATABASE_WRITTEN "$EVIDENCE/apply.txt")"; [[ "$LIVE_DATABASE_WRITTEN" == true || "$LIVE_DATABASE_WRITTEN" == false ]] || LIVE_DATABASE_WRITTEN=false
DATABASE_SCHEMA_CHANGED="$(last_field DATABASE_SCHEMA_CHANGED "$EVIDENCE/apply.txt")"; [[ "$DATABASE_SCHEMA_CHANGED" == true || "$DATABASE_SCHEMA_CHANGED" == false ]] || DATABASE_SCHEMA_CHANGED=false
SOURCE_ROLLBACK_STATUS="$(last_field SOURCE_ROLLBACK_STATUS "$EVIDENCE/apply.txt")"; [[ -n "$SOURCE_ROLLBACK_STATUS" ]] || SOURCE_ROLLBACK_STATUS=not_started
DATABASE_ROLLBACK_STATUS="$(last_field DATABASE_ROLLBACK_STATUS "$EVIDENCE/apply.txt")"; [[ -n "$DATABASE_ROLLBACK_STATUS" ]] || DATABASE_ROLLBACK_STATUS=not_started
BACKEND_RECOVERY_STATUS="$(last_field BACKEND_RECOVERY_STATUS "$EVIDENCE/apply.txt")"; [[ -n "$BACKEND_RECOVERY_STATUS" ]] || BACKEND_RECOVERY_STATUS=not_started
BACKUP_DIR="$(last_field BACKUP_DIR "$EVIDENCE/apply.txt")"
if [[ "$target_rc" -ne 0 ]]; then
  [[ -s "$EVIDENCE/apply.txt" ]] || { STOP_DETAIL=target_transport_or_no_apply_evidence; false; }
  [[ "$CORE_CHANGE_COMPLETE" == false ]] || { STOP_DETAIL=target_failed_after_core_marker; false; }
  if [[ "$(last_field BACKUP_READY "$EVIDENCE/apply.txt")" == true ]]; then "$ROOT/scripts/apply-result-validate.sh" "$EVIDENCE/apply.txt" STOP > "$EVIDENCE/apply-validation.txt" || { STOP_DETAIL=target_rollback_semantics; false; }; fi
  STOP_DETAIL=target_apply; false
fi
"$ROOT/scripts/apply-result-validate.sh" "$EVIDENCE/apply.txt" PASS > "$EVIDENCE/apply-validation.txt" || { STOP_DETAIL=apply_semantics; false; }
router_step_phase_complete apply encrypted_backup_restore_migration_allocator_credential_ack_retry_and_source_applied

router_step_phase_begin machine_close
if [[ "$SELFTEST" == true ]]; then self_close > "$EVIDENCE/machine-close.txt"; else /opt/router-ops/bin/router-machine-close-safe vm121 "$STEP: durable Domain V2 WireGuard tunnel-IP reservation, credential transaction, retry/ACK and existing VM100 lifecycle adapter; agent remains inactive" > "$EVIDENCE/machine-close.txt" 2>&1; fi
"$ROOT/scripts/machine-close-validate.sh" "$EVIDENCE/machine-close.txt" "$VM121_EXPECTED_TREE" "$VM121_EXPECTED_COUNT" > "$EVIDENCE/machine-close-validation.txt" || { STOP_DETAIL=vm121_machine_close; false; }
VM121_NEW_COMMIT="$(last_field VM121_NEW_COMMIT "$EVIDENCE/machine-close-validation.txt")"; VM121_NEW_TREE="$VM121_EXPECTED_TREE"; VM121_NEW_FILE_COUNT="$VM121_EXPECTED_COUNT"; VM121_PUBLIC_URL="$(last_field VM121_NEW_PUBLIC_URL "$EVIDENCE/machine-close-validation.txt")"
cleanup_remote
router_step_phase_complete machine_close vm121_source_closed_and_published

router_step_phase_begin postcheck
if [[ "$SELFTEST" == true ]]; then
  self_source vm121 "$VM121_NEW_COMMIT" "$VM121_EXPECTED_TREE" "$VM121_EXPECTED_COUNT" > "$EVIDENCE/post-vm121-source.txt"
  self_source vm100 "$VM100_COMMIT" "$VM100_TREE" "$VM100_COUNT" > "$EVIDENCE/post-vm100-source.txt"
  self_source vm101 "$VM101_COMMIT" "$VM101_TREE" "$VM101_COUNT" > "$EVIDENCE/post-vm101-source.txt"
  self_post_live > "$EVIDENCE/post-live.txt"
else
  ssh -T vm121 /usr/local/sbin/router-vm121-git-publish.sh --check > "$EVIDENCE/post-vm121-source.txt" 2>&1
  ssh -T pve-mgts "ssh -n -o BatchMode=yes -o ConnectTimeout=10 -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.1 /usr/local/sbin/router-vm100-git-publish.sh --check" > "$EVIDENCE/post-vm100-source.txt" 2>&1
  ssh -T pve-mgts "ssh -n -o BatchMode=yes -o ConnectTimeout=10 -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 /usr/local/sbin/router-vm101-git-publish.sh --check" > "$EVIDENCE/post-vm101-source.txt" 2>&1
  ssh -T vm121 /bin/bash -s > "$EVIDENCE/post-live.txt" 2>&1 <<'VM121POST'
set -Eeuo pipefail
sha(){ sha256sum "$1" | awk '{print $1}'; }
[[ "$(sha /opt/wg-access/backend/alembic/versions/0004_profile_provisioning_boundary.py)" == 9c86ef1c7a998a5bd89a9c97df44529b4436356e7eaaca849d3bb7c723964220 ]]
[[ "$(sha /opt/wg-access/backend/app/models/core.py)" == e6de23a9fe506d6ee155b36ff79321bb75d1a2275819309e849d27beb7f7a4f6 ]]
[[ "$(sha /opt/wg-access/backend/app/services/wireguard.py)" == 180f727556336b7ed0eca6fa3aa4ec4c9a2b0dc1de26412e22cd91bd3fdeda26 ]]
[[ "$(sha /opt/wg-access/backend/app/services/domain_v2.py)" == 4a5ba5b85198c3a07d36db658f9fed260cba5face2129809886fed53eec06ac8 ]]
[[ "$(sha /opt/wg-access/backend/app/api/agent.py)" == 3eafe044e2037896acf935bc875faafe43dc99c6010cc4d83f87e48c239abdfc ]]
[[ "$(sha /opt/wg-access/agent/wg_access_agent.py)" == b4b76e8256390a1a1629f0c1cbd3280231e3cff14334d50d57925d910df40e0c ]]
curl -fsS --max-time 5 http://127.0.0.1:18080/health >/dev/null
curl -fsS --max-time 5 http://127.0.0.1:18080/health/db >/dev/null
PG=wgaccess-postgres; U="$(docker exec "$PG" sh -lc 'printf %s "$POSTGRES_USER"')"; D="$(docker exec "$PG" sh -lc 'printf %s "$POSTGRES_DB"')"; Q(){ docker exec "$PG" psql -v ON_ERROR_STOP=1 -U "$U" -d "$D" -Atqc "$1"; }
ALEMBIC_VERSION="$(Q 'SELECT version_num FROM alembic_version')"
BUSINESS_ROWS="$(Q "SELECT (SELECT count(*) FROM users)+(SELECT count(*) FROM plans)+(SELECT count(*) FROM access_grants)+(SELECT count(*) FROM access_grant_protocol_limits)+(SELECT count(*) FROM invites)+(SELECT count(*) FROM invite_redemptions)+(SELECT count(*) FROM magic_link_tokens)+(SELECT count(*) FROM auth_sessions)+(SELECT count(*) FROM connection_profiles)+(SELECT count(*) FROM peer_credentials)+(SELECT count(*) FROM audit_events)+(SELECT count(*) FROM invite_codes)+(SELECT count(*) FROM orders)+(SELECT count(*) FROM subscriptions)+(SELECT count(*) FROM peers)+(SELECT count(*) FROM provisioning_jobs)+(SELECT count(*) FROM peer_egress_leases)")"
PROFILE_ROWS="$(Q 'SELECT count(*) FROM connection_profiles')"; CRED_ROWS="$(Q 'SELECT count(*) FROM peer_credentials')"; JOB_ROWS="$(Q 'SELECT count(*) FROM provisioning_jobs')"
COLS="$(Q "SELECT count(*) FROM information_schema.columns WHERE table_schema='public' AND table_name='connection_profiles' AND column_name IN ('tunnel_ip','tunnel_ip_reserved_at','tunnel_ip_released_at')")"
IDX="$(Q "SELECT count(*) FROM pg_indexes WHERE schemaname='public' AND tablename='connection_profiles' AND indexname='uq_connection_profiles_node_tunnel_ip_reserved'")"
[[ "$ALEMBIC_VERSION" == 0004_profile_provisioning_boundary && "$BUSINESS_ROWS" == 0 && "$PROFILE_ROWS" == 0 && "$CRED_ROWS" == 0 && "$JOB_ROWS" == 0 && "$COLS" == 3 && "$IDX" == 1 ]]
AP="$(systemctl is-active wg-access-agent.path 2>/dev/null || true)"; EP="$(systemctl is-enabled wg-access-agent.path 2>/dev/null || true)"; AT="$(systemctl is-active wg-access-agent.timer 2>/dev/null || true)"; ET="$(systemctl is-enabled wg-access-agent.timer 2>/dev/null || true)"; AS="$(systemctl is-active wg-access-agent.service 2>/dev/null || true)"
[[ "$AP" == inactive && "$EP" == disabled && "$AT" == inactive && "$ET" == disabled && "$AS" == inactive ]]
echo "ALEMBIC_VERSION=$ALEMBIC_VERSION"; echo "BUSINESS_ROWS=$BUSINESS_ROWS"; echo "CONNECTION_PROFILE_ROWS=$PROFILE_ROWS"; echo "PEER_CREDENTIAL_ROWS=$CRED_ROWS"; echo "PROVISIONING_JOB_ROWS=$JOB_ROWS"; echo "TUNNEL_IP_COLUMN_COUNT=$COLS"; echo "TUNNEL_IP_UNIQUE_INDEX_COUNT=$IDX"; echo "AGENT_PATH_ACTIVE=$AP"; echo "AGENT_PATH_ENABLED=$EP"; echo "AGENT_TIMER_ACTIVE=$AT"; echo "AGENT_TIMER_ENABLED=$ET"; echo "AGENT_SERVICE_ACTIVE=$AS"; echo RUNTIME_PROVISIONING_ACTIVE=false; echo EXTERNAL_ONBOARDING_ACTIVE=false; echo RESULT=PASS_P24_R10_POST_LIVE
VM121POST
fi
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/post-vm121-source.txt" vm121 "$VM121_NEW_COMMIT" "$VM121_EXPECTED_TREE" "$VM121_EXPECTED_COUNT" 0 > "$EVIDENCE/post-vm121-source-validation.txt" || { STOP_DETAIL=post_vm121_source; false; }
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/post-vm100-source.txt" vm100 "$VM100_COMMIT" "$VM100_TREE" "$VM100_COUNT" 0 > "$EVIDENCE/post-vm100-source-validation.txt" || { STOP_DETAIL=post_vm100_source; false; }
"$ROOT/scripts/source-check-validate.sh" "$EVIDENCE/post-vm101-source.txt" vm101 "$VM101_COMMIT" "$VM101_TREE" "$VM101_COUNT" 0 > "$EVIDENCE/post-vm101-source-validation.txt" || { STOP_DETAIL=post_vm101_source; false; }
for kv in 'RESULT=PASS_P24_R10_POST_LIVE' 'ALEMBIC_VERSION=0004_profile_provisioning_boundary' 'BUSINESS_ROWS=0' 'CONNECTION_PROFILE_ROWS=0' 'PEER_CREDENTIAL_ROWS=0' 'PROVISIONING_JOB_ROWS=0' 'TUNNEL_IP_COLUMN_COUNT=3' 'TUNNEL_IP_UNIQUE_INDEX_COUNT=1' 'AGENT_PATH_ACTIVE=inactive' 'AGENT_PATH_ENABLED=disabled' 'AGENT_TIMER_ACTIVE=inactive' 'AGENT_TIMER_ENABLED=disabled' 'AGENT_SERVICE_ACTIVE=inactive'; do grep -Fqx "$kv" "$EVIDENCE/post-live.txt" || { STOP_DETAIL=post_live_semantics; false; }; done
router_step_phase_complete postcheck exact_source_database_backend_and_inactive_agent_verified

router_step_phase_begin report_publish
cat > "$REPORT/report.txt" <<EOR
RESULT=PASS_P24_VM121_DURABLE_PROFILE_PROVISIONING_BOUNDARY
REVISION=R10
CORE_CHANGE_COMPLETE=true
CORE_CHANGE_REPEATED=false
SOURCE_CHANGED=true
LIVE_DATABASE_WRITTEN=true
DATABASE_SCHEMA_CHANGED=true
ALEMBIC_VERSION=0004_profile_provisioning_boundary
BUSINESS_ROWS=0
CONNECTION_PROFILE_ROWS=0
PEER_CREDENTIAL_ROWS=0
PROVISIONING_JOB_ROWS=0
TUNNEL_IP_DURABLE=true
TUNNEL_IP_UNIQUE_RESERVATION=true
WIREGUARD_POOL_REUSED_EXISTING_SETTINGS=true
ALLOCATOR_CONCURRENCY_UNIQUE=PASS
LEGACY_COLLISION_AVOIDANCE=PASS
CREDENTIAL_TRANSACTION=PASS
SAFE_JOB_PAYLOAD=PASS
DISABLE_RESERVATION_HELD_UNTIL_ACK=PASS
REUSE_AFTER_CONFIRMED_DISABLE=PASS
RETRY_BACKOFF_RESERVATION=PASS
EXISTING_VM100_LIFECYCLE_ADAPTER_REUSED=true
AGENT_DIRECT_RUNTIME_WRITE_PRESENT=false
RUNTIME_PROVISIONING_ACTIVE=false
EXTERNAL_ONBOARDING_ACTIVE=false
SOURCE_ROLLBACK_STATUS=not_required
DATABASE_ROLLBACK_STATUS=not_required
BACKEND_RECOVERY_STATUS=PASS
ENCRYPTED_BACKUP_PRESENT=true
BACKUP_RESTORE_PROOF=PASS
BACKUP_DIR=$BACKUP_DIR
VM100_COMMIT=$VM100_COMMIT
VM100_TREE=$VM100_TREE
VM100_FILE_COUNT=$VM100_COUNT
VM100_PUBLIC_URL=$VM100_PUBLIC_URL
VM101_COMMIT=$VM101_COMMIT
VM101_TREE=$VM101_TREE
VM101_FILE_COUNT=$VM101_COUNT
VM101_PUBLIC_URL=$VM101_PUBLIC_URL
VM121_BASE_COMMIT=$VM121_BASE_COMMIT
VM121_COMMIT=$VM121_NEW_COMMIT
VM121_TREE=$VM121_NEW_TREE
VM121_FILE_COUNT=$VM121_NEW_FILE_COUNT
VM121_PUBLIC_URL=$VM121_PUBLIC_URL
LOCAL_PLAN_URL=https://reports.secret-studio.ru/latest/20260719-080444_local_architecture_plan_vm101_autonomous_hmn_recovery_r19/
GLOBAL_PLAN_URL=https://reports.secret-studio.ru/latest/20260802-105248_global_project_plan_wg_paid_after_r20qw/
ACCESS_MAP_URL=https://reports.secret-studio.ru/latest/20260715-210236_access_map_canonical_current/
RUNTIME_IMPACT=true
COPY_VERIFY=PASS
NEXT_ACTION=P25 synthetic WireGuard Domain V2 end-to-end provisioning through the existing VM121 agent and VM100 lifecycle; enable only controlled test execution, no public onboarding
EOR
cp "$REPORT/report.txt" "$REPORT/verify.txt"; cp "$ROOT/scripts/run-step.sh" "$REPORT/executed-step.sh"; cp "$ROOT/release-info.json" "$REPORT/release-info.json"; cp "$ROOT/rollback/README.md" "$REPORT/rollback.txt"
for f in apply-validation.txt machine-close-validation.txt post-vm121-source-validation.txt post-vm100-source-validation.txt post-vm101-source-validation.txt post-live.txt; do cp "$EVIDENCE/$f" "$REPORT/$f"; done
if [[ "$SELFTEST" == true ]]; then DEST="${ROUTER_PUBLIC_ROOT:?}/latest/p24-r10-pass-selftest"; rm -rf "$DEST"; mkdir -p "$DEST"; cp -a "$REPORT"/. "$DEST"/; STEP_REPORT_URL=selftest://p24-r10-pass/; else args=(); while IFS= read -r f; do args+=("$f" "$(basename "$f")"); done < <(find "$REPORT" -maxdepth 1 -type f -print | LC_ALL=C sort); router_step_publish_payload step050m07p24_r10_durable_profile_provisioning_boundary_continuation "$REPORT" "$PAYLOAD" "$CURRENT" "$EVENTS" "$FINAL_ENV" "${args[@]}"; STEP_REPORT_URL="$(last_field PUBLIC_URL "$FINAL_ENV")"; fi
router_step_phase_complete report_publish report_published
router_step_phase_begin archive; archive_latest; router_step_phase_complete archive latest_archived
STOP_DETAIL=none; write_child PASS_P24_VM121_DURABLE_PROFILE_PROVISIONING_BOUNDARY 0; trap - ERR; exit 0
