#!/usr/bin/env bash set -euo pipefail readonly SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" readonly DEFAULT_SOURCE_ROOT="$(CDPATH= cd -- "${SCRIPT_DIR}/../.." && pwd)" readonly TARGET="Administrator@192.168.0.99" readonly SOURCE_HOST_IPV4="192.168.0.110" readonly GITEA_ORIGIN_HTTPS="https://gitea.wooo.work/wooo/awoooi.git" readonly GITEA_ORIGIN_HTTP_INTERNAL="http://192.168.0.110:3000/wooo/awoooi.git" readonly GITEA_ORIGIN_SSH_INTERNAL="ssh://git@192.168.0.110:2222/wooo/awoooi.git" readonly RECEIVER_RELATIVE="scripts/reboot-recovery/agent99-remote-atomic-deploy-receiver.ps1" readonly PREFLIGHT_RELATIVE="scripts/reboot-recovery/agent99-live-preflight.ps1" readonly WRAPPER_RELATIVE="scripts/reboot-recovery/deploy-agent99-via-windows99-ssh.sh" readonly REMOTE_STDIN_SENTINEL="__AWOOOI_AGENT99_REMOTE_BOOTSTRAP_END_V1__" RUNTIME_FILES=( "agent99-bootstrap.ps1" "agent99-contract-check.ps1" "agent99-control-plane.ps1" "agent99-deploy.ps1" "agent99-register-tasks.ps1" "agent99-sre-alert-inbox.ps1" "agent99-sre-alert-relay.ps1" "agent99-submit-request.ps1" "agent99-synthetic-tests.ps1" "agent99-telegram-inbox.ps1" "agent99-windows-update-policy.ps1" "host-reboot-scorecard.ps1" "agent99.config.example.json" "agent99.config.99.example.json" ) MODE="check" MODE_SELECTION="default" SOURCE_ROOT="${DEFAULT_SOURCE_ROOT}" SOURCE_REVISION="" TRACE_ID="" RUN_ID="" WORK_ITEM_ID="" IDENTITY_FILE="" KNOWN_HOSTS_FILE="${HOME:-}/.ssh/known_hosts" CONNECT_TIMEOUT_SECONDS="8" REMOTE_EXECUTION_TIMEOUT_SECONDS="180" usage() { printf '%s\n' \ "Usage: $0 [--check|--apply] [options]" \ "" \ "Default is a remote no-write check/plan against fixed target ${TARGET}." \ "Apply requires --apply plus --trace-id, --run-id, and --work-item-id." \ "" \ "Options:" \ " --check No-write transport and envelope check (default)." \ " --apply Stage, ValidateOnly, bounded promote, and verify." \ " --trace-id ID Controlled-apply trace identity." \ " --run-id ID Controlled-apply run identity." \ " --work-item-id ID Controlled-apply work-item identity." \ " --source-root PATH Checkout root (default: repository root)." \ " --source-revision SHA Exact 40-character Git commit (default: HEAD)." \ " --identity-file PATH Existing SSH identity; wrapper never reads or prints its contents." \ " --known-hosts-file PATH Pinned known_hosts path (default: ~/.ssh/known_hosts)." \ " --connect-timeout SECONDS SSH connect timeout from 1 through 30 (default: 8)." \ " -h, --help Show this help." } fail() { printf 'agent99_transport_error=%s\n' "$1" >&2 exit 64 } require_value() { [[ $# -ge 2 && -n "$2" ]] || fail "missing_option_value" } while [[ $# -gt 0 ]]; do case "$1" in --check) [[ "${MODE_SELECTION}" != "apply" ]] || fail "conflicting_mode_flags" MODE="check" MODE_SELECTION="check" shift ;; --apply) [[ "${MODE_SELECTION}" != "check" ]] || fail "conflicting_mode_flags" MODE="apply" MODE_SELECTION="apply" shift ;; --trace-id) require_value "$@" TRACE_ID="$2" shift 2 ;; --run-id) require_value "$@" RUN_ID="$2" shift 2 ;; --work-item-id) require_value "$@" WORK_ITEM_ID="$2" shift 2 ;; --source-root) require_value "$@" SOURCE_ROOT="$2" shift 2 ;; --source-revision) require_value "$@" SOURCE_REVISION="$2" shift 2 ;; --identity-file) require_value "$@" IDENTITY_FILE="$2" shift 2 ;; --known-hosts-file) require_value "$@" KNOWN_HOSTS_FILE="$2" shift 2 ;; --connect-timeout) require_value "$@" CONNECT_TIMEOUT_SECONDS="$2" shift 2 ;; -h|--help) usage exit 0 ;; *) fail "unsupported_option" ;; esac done [[ "${CONNECT_TIMEOUT_SECONDS}" =~ ^[0-9]+$ ]] || fail "invalid_connect_timeout" (( CONNECT_TIMEOUT_SECONDS >= 1 && CONNECT_TIMEOUT_SECONDS <= 30 )) || fail "invalid_connect_timeout" if [[ "${MODE}" == "apply" ]]; then REMOTE_EXECUTION_TIMEOUT_SECONDS="2400" readonly SAFE_ID_PATTERN='^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$' [[ "${TRACE_ID}" =~ ${SAFE_ID_PATTERN} ]] || fail "apply_trace_id_missing_or_invalid" [[ "${RUN_ID}" =~ ${SAFE_ID_PATTERN} ]] || fail "apply_run_id_missing_or_invalid" [[ "${WORK_ITEM_ID}" =~ ${SAFE_ID_PATTERN} ]] || fail "apply_work_item_id_missing_or_invalid" fi for dependency in git python3 ssh scp mktemp hostname timeout; do command -v "${dependency}" >/dev/null 2>&1 || fail "required_command_missing_${dependency}" done SOURCE_HOST_VERIFIED=0 read -r -a LOCAL_ADDRESSES <<<"$(hostname -I 2>/dev/null || true)" for local_address in "${LOCAL_ADDRESSES[@]}"; do if [[ "${local_address%%/*}" == "${SOURCE_HOST_IPV4}" ]]; then SOURCE_HOST_VERIFIED=1 break fi done [[ "${SOURCE_HOST_VERIFIED}" == "1" ]] || fail "source_host_is_not_110" [[ -d "${SOURCE_ROOT}" ]] || fail "source_root_missing" SOURCE_ROOT="$(CDPATH= cd -- "${SOURCE_ROOT}" && pwd)" ORIGIN_URL="$(git -C "${SOURCE_ROOT}" remote get-url origin 2>/dev/null)" || fail "origin_remote_missing" case "${ORIGIN_URL}" in "${GITEA_ORIGIN_HTTPS}"|"${GITEA_ORIGIN_HTTP_INTERNAL}"|"${GITEA_ORIGIN_SSH_INTERNAL}") ;; *) fail "origin_is_not_fixed_internal_gitea" ;; esac git -C "${SOURCE_ROOT}" fetch --quiet --no-tags origin \ '+refs/heads/main:refs/remotes/origin/main' || fail "fresh_origin_main_fetch_failed" ORIGIN_MAIN_REVISION="$(git -C "${SOURCE_ROOT}" rev-parse --verify 'refs/remotes/origin/main^{commit}' 2>/dev/null)" \ || fail "fresh_origin_main_revision_unavailable" ORIGIN_MAIN_REVISION="$(printf '%s' "${ORIGIN_MAIN_REVISION}" | tr '[:upper:]' '[:lower:]')" [[ -f "${KNOWN_HOSTS_FILE}" ]] || fail "known_hosts_file_missing" if [[ -n "${IDENTITY_FILE}" ]]; then [[ -f "${IDENTITY_FILE}" ]] || fail "identity_file_missing" fi if [[ -z "${SOURCE_REVISION}" ]]; then SOURCE_REVISION="${ORIGIN_MAIN_REVISION}" fi SOURCE_REVISION="$(printf '%s' "${SOURCE_REVISION}" | tr '[:upper:]' '[:lower:]')" [[ "${SOURCE_REVISION}" =~ ^[0-9a-f]{40}$ ]] || fail "source_revision_must_be_full_commit_sha" git -C "${SOURCE_ROOT}" cat-file -e "${SOURCE_REVISION}^{commit}" 2>/dev/null || fail "source_revision_not_found" [[ "${SOURCE_REVISION}" == "${ORIGIN_MAIN_REVISION}" ]] || fail "source_revision_is_not_fresh_origin_main" SOURCE_BOUND_FILES=( "${RUNTIME_FILES[@]}" "${PREFLIGHT_RELATIVE}" "${RECEIVER_RELATIVE}" "${WRAPPER_RELATIVE}" ) for relative_path in "${SOURCE_BOUND_FILES[@]}"; do [[ -f "${SOURCE_ROOT}/${relative_path}" ]] || fail "source_bound_file_missing" git -C "${SOURCE_ROOT}" ls-files --error-unmatch -- "${relative_path}" >/dev/null 2>&1 || fail "source_bound_file_untracked" done git -C "${SOURCE_ROOT}" diff --quiet "${SOURCE_REVISION}" -- "${SOURCE_BOUND_FILES[@]}" || fail "source_bundle_differs_from_revision" umask 077 WORK_DIR="$(mktemp -d /tmp/awoooi-agent99-transport.XXXXXXXX)" cleanup() { rm -rf -- "${WORK_DIR}" } trap cleanup EXIT HUP INT TERM ENVELOPE_PATH="${WORK_DIR}/envelope.json" BOOTSTRAP_PATH="${WORK_DIR}/remote-bootstrap.ps1" BOOTSTRAP_PAYLOAD_PATH="${WORK_DIR}/remote-bootstrap.ps1.gz.b64" python3 - \ "${SOURCE_ROOT}" \ "${SOURCE_REVISION}" \ "${MODE}" \ "${TRACE_ID}" \ "${RUN_ID}" \ "${WORK_ITEM_ID}" \ "${ENVELOPE_PATH}" \ "${RUNTIME_FILES[@]}" <<'PY' from __future__ import annotations import base64 import hashlib import json import sys from pathlib import Path source_root = Path(sys.argv[1]) source_revision, mode = sys.argv[2:4] trace_id, run_id, work_item_id = sys.argv[4:7] output_path = Path(sys.argv[7]) runtime_names = sys.argv[8:] if len(runtime_names) != 14 or len(set(runtime_names)) != 14: raise SystemExit("fixed_runtime_file_contract_failed") files: list[dict[str, str]] = [] manifest_rows: list[str] = [] for name in runtime_names: if Path(name).name != name: raise SystemExit("runtime_filename_not_flat") content = (source_root / name).read_bytes() digest = hashlib.sha256(content).hexdigest() files.append( { "name": name, "sha256": digest, "contentBase64": base64.b64encode(content).decode("ascii"), } ) manifest_rows.append(f"{name}\t{digest}\n") manifest_sha256 = hashlib.sha256("".join(manifest_rows).encode("utf-8")).hexdigest() preflight_path = source_root / "scripts/reboot-recovery/agent99-live-preflight.ps1" preflight_content = preflight_path.read_bytes() envelope = { "schemaVersion": "agent99_remote_atomic_deploy_envelope_v1", "sourceHostAlias": "110", "targetHostAlias": "99", "transport": "110_to_99_ssh_publickey", "transportPayloadMode": ( "ephemeral_file_delete_before_receiver" if mode == "apply" else "control_command_no_stdin" ), "transportPayloadContainsSecrets": False, "mode": mode, "traceId": trace_id, "runId": run_id, "workItemId": work_item_id, "sourceRevision": source_revision, "expectedRuntimeFileCount": 14, "manifestSha256": manifest_sha256, "files": files, "livePreflight": { "name": preflight_path.name, "sha256": hashlib.sha256(preflight_content).hexdigest(), "contentBase64": base64.b64encode(preflight_content).decode("ascii"), }, } output_path.write_text( json.dumps(envelope, separators=(",", ":"), ensure_ascii=True), encoding="utf-8", ) PY python3 - \ "${SOURCE_ROOT}/${RECEIVER_RELATIVE}" \ "${ENVELOPE_PATH}" \ "${BOOTSTRAP_PATH}" <<'PY' from __future__ import annotations import base64 import json import sys from pathlib import Path receiver_path, envelope_path, output_path = map(Path, sys.argv[1:4]) receiver_base64 = base64.b64encode(receiver_path.read_bytes()).decode("ascii") envelope_base64 = base64.b64encode(envelope_path.read_bytes()).decode("ascii") envelope_mode = json.loads(envelope_path.read_text(encoding="utf-8"))["mode"] transport_delete_switch = ( " -TransportPayloadDeletedBeforeReceiver" if envelope_mode == "apply" else "" ) bootstrap = ( "$ErrorActionPreference = 'Stop'\r\n" f"$receiverText = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('{receiver_base64}'))\r\n" f"$envelopeText = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('{envelope_base64}'))\r\n" "& ([ScriptBlock]::Create($receiverText)) -EnvelopeJson $envelopeText" f"{transport_delete_switch}\r\n" ) output_path.write_text(bootstrap, encoding="utf-8") PY python3 - \ "${BOOTSTRAP_PATH}" \ "${BOOTSTRAP_PAYLOAD_PATH}" \ "${REMOTE_STDIN_SENTINEL}" <<'PY' from __future__ import annotations import base64 import gzip import sys from pathlib import Path bootstrap_path, output_path = map(Path, sys.argv[1:3]) sentinel = sys.argv[3] compressed = gzip.compress( bootstrap_path.read_bytes(), compresslevel=9, mtime=0, ) payload = base64.b64encode(compressed).decode("ascii") line_width = 65536 payload_lines = [ payload[offset : offset + line_width] for offset in range(0, len(payload), line_width) ] if not payload_lines or len(payload_lines) > 8: raise SystemExit("remote_bootstrap_payload_line_contract_failed") output_path.write_text( "\n".join(payload_lines) + "\n" + sentinel + "\n", encoding="ascii", ) PY TRANSPORT_TOKEN="$(python3 - "${BOOTSTRAP_PAYLOAD_PATH}" <<'PY' from __future__ import annotations import hashlib import sys from pathlib import Path print(hashlib.sha256(Path(sys.argv[1]).read_bytes()).hexdigest()[:20]) PY )" readonly TRANSPORT_TOKEN readonly REMOTE_TRANSPORT_DIR_WINDOWS='C:\Wooo\Agent99\deploy\transport-inbox' readonly REMOTE_TRANSPORT_PATH_WINDOWS="${REMOTE_TRANSPORT_DIR_WINDOWS}\\agent99-bootstrap-${TRANSPORT_TOKEN}.b64" readonly REMOTE_TRANSPORT_PATH_SCP="C:/Wooo/Agent99/deploy/transport-inbox/agent99-bootstrap-${TRANSPORT_TOKEN}.b64" SSH_OPTIONS=( -T -o BatchMode=yes -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o StrictHostKeyChecking=yes -o "UserKnownHostsFile=${KNOWN_HOSTS_FILE}" -o "ConnectTimeout=${CONNECT_TIMEOUT_SECONDS}" -o ConnectionAttempts=1 -o ServerAliveInterval=5 -o ServerAliveCountMax=2 -o LogLevel=ERROR -o IdentitiesOnly=yes ) if [[ -n "${IDENTITY_FILE}" ]]; then SSH_OPTIONS+=( -i "${IDENTITY_FILE}" ) fi SCP_OPTIONS=( -q -o BatchMode=yes -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o StrictHostKeyChecking=yes -o "UserKnownHostsFile=${KNOWN_HOSTS_FILE}" -o "ConnectTimeout=${CONNECT_TIMEOUT_SECONDS}" -o ConnectionAttempts=1 -o ServerAliveInterval=5 -o ServerAliveCountMax=2 -o LogLevel=ERROR -o IdentitiesOnly=yes ) if [[ -n "${IDENTITY_FILE}" ]]; then SCP_OPTIONS+=( -i "${IDENTITY_FILE}" ) fi readonly REMOTE_CHECK_COMMAND="$(python3 - "${ENVELOPE_PATH}" <<'PY' from __future__ import annotations import base64 import hashlib import json import sys from pathlib import Path envelope = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8")) source_revision = envelope["sourceRevision"] manifest_sha256 = envelope["manifestSha256"] stage_identity = f"check||||{source_revision}" stage_token = hashlib.sha256(stage_identity.encode("utf-8")).hexdigest()[:20] script = r'''$ErrorActionPreference='Stop';$ProgressPreference='SilentlyContinue' $a='C:\Wooo\Agent99';$b=Join-Path $a 'bin';$p=Join-Path $a 'state\runtime-manifest.json' $r=[ordered]@{exists=$false;sourceRevision='';runtimeMatched=$false;recordedRuntimeMatched=$false;fileCount=0;mismatchCount=-1;recordedMismatchCount=-1;parseError=''} if(Test-Path -LiteralPath $p -PathType Leaf){try{$m=Get-Content -LiteralPath $p -Raw|ConvertFrom-Json;$rows=@($m.files);$seen=@{};$bad=0;foreach($x in $rows){$n=[string]$x.name;if(!$n-or[IO.Path]::GetFileName($n)-ne$n-or$seen.ContainsKey($n)){$bad++;continue};$seen[$n]=1;$q=Join-Path $b $n;$h=if(Test-Path -LiteralPath $q -PathType Leaf){(Get-FileHash -LiteralPath $q -Algorithm SHA256).Hash.ToLowerInvariant()}else{'missing'};if(([string]$x.runtimeSha256).ToLowerInvariant()-ne$h){$bad++}};$r.exists=$true;$r.sourceRevision=[string]$m.sourceRevision;$r.recordedRuntimeMatched=[bool]$m.runtimeMatched;$r.fileCount=[int]$m.fileCount;$r.mismatchCount=$bad;$r.recordedMismatchCount=[int]$m.mismatchCount;$r.runtimeMatched=[bool]($m.runtimeMatched-and$m.fileCount-eq 14-and$m.mismatchCount-eq 0-and$rows.Count-eq 14-and$seen.Count-eq 14-and$bad-eq 0)}catch{$r.exists=$true;$r.parseError=$_.Exception.GetType().Name}} $c=[ordered]@{executed=$false;ok=$false;exitCode=-1;errorType=''} try{& powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $b 'agent99-contract-check.ps1') -SourceRoot $b 2>$null|Out-Null;$c.executed=$true;$c.exitCode=$LASTEXITCODE;$c.ok=[bool]($c.exitCode-eq 0)}catch{$c.executed=$true;$c.errorType=$_.Exception.GetType().Name} $z=[ordered]@{};foreach($n in 'remoteWritePerformed,liveRuntimeWritePerformed,livePromotionAttempted,livePromotionPerformed,secretValueRead,privateKeyValueRead,tokenValueRead,environmentSecretRead,uiInteraction,vmPowerChange,hostReboot,serviceRestart,scheduledTaskRestart,scheduledTaskModification'.Split(',')){$z[$n]=$false} $ready=[bool]($c.executed-and$c.ok-and$c.exitCode-eq 0) $status=if($ready){'check_ready'}else{'check_failed_no_apply'} $next=if($ready){'rerun_with_apply_and_trace_run_work_item_after_source_commit_and_transport_check'}else{'repair_runtime_contract_before_apply'} [ordered]@{schemaVersion='agent99_remote_atomic_deploy_receipt_v1';status=$status;mode='check';sourceRevision='__SOURCE_REVISION__';expectedRuntimeFileCount=14;manifestSha256='__MANIFEST_SHA256__';plannedStagingPath='C:\Wooo\Agent99\deploy\remote-source-__STAGE_TOKEN__';runtimeManifest=[pscustomobject]$r;runtimeContract=[pscustomobject]$c;livePreflight=[ordered]@{executed=$false;reason='apply_only_after_validate_only'};transportPayloadMode='control_command_no_stdin';transientTransportPayloadStored=$false;transientTransportPayloadDeletedBeforeReceiver=$false;transportPayloadContainsSecrets=$false;operationBoundaries=$z;nextSafeAction=$next}|ConvertTo-Json -Compress -Depth 8 if(-not$ready){exit 65}''' script = ( script.replace("__SOURCE_REVISION__", source_revision) .replace("__MANIFEST_SHA256__", manifest_sha256) .replace("__STAGE_TOKEN__", stage_token) ) encoded = base64.b64encode(script.encode("utf-16le")).decode("ascii") print( "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass " f"-EncodedCommand {encoded}" ) PY )" readonly REMOTE_PREPARE_COMMAND="$(python3 - \ "${REMOTE_TRANSPORT_DIR_WINDOWS}" \ "${REMOTE_TRANSPORT_PATH_WINDOWS}" <<'PY' from __future__ import annotations import base64 import sys directory = sys.argv[1].replace("'", "''") path = sys.argv[2].replace("'", "''") script = rf'''$ErrorActionPreference = "Stop" $directory = '{directory}' $payloadPath = '{path}' New-Item -ItemType Directory -Force -Path $directory | Out-Null if (Test-Path -LiteralPath $payloadPath) {{ Remove-Item -LiteralPath $payloadPath -Force }} if (Test-Path -LiteralPath $payloadPath) {{ throw "remote_transport_stale_payload_cleanup_failed" }}''' encoded = base64.b64encode(script.encode("utf-16le")).decode("ascii") print( "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass " f"-EncodedCommand {encoded}" ) PY )" readonly REMOTE_FILE_COMMAND="$(python3 - \ "${REMOTE_TRANSPORT_PATH_WINDOWS}" \ "${REMOTE_STDIN_SENTINEL}" <<'PY' from __future__ import annotations import base64 import sys path = sys.argv[1].replace("'", "''") sentinel = sys.argv[2].replace("'", "''") decoder = rf'''$ErrorActionPreference = "Stop" $payloadPath = '{path}' $sentinel = '{sentinel}' $allLines = @() try {{ $payloadFile = Get-Item -LiteralPath $payloadPath -ErrorAction Stop if ($payloadFile.Length -le 0 -or $payloadFile.Length -gt 1048576) {{ throw "remote_bootstrap_file_size_invalid" }} $allLines = @([IO.File]::ReadAllLines($payloadPath, [Text.Encoding]::ASCII)) }} finally {{ if (Test-Path -LiteralPath $payloadPath) {{ Remove-Item -LiteralPath $payloadPath -Force -ErrorAction SilentlyContinue }} }} if (Test-Path -LiteralPath $payloadPath) {{ throw "remote_bootstrap_file_delete_failed" }} if ($allLines.Count -lt 2 -or $allLines[-1] -cne $sentinel) {{ throw "remote_bootstrap_sentinel_missing" }} $payloadLines = @($allLines[0..($allLines.Count - 2)]) $charCount = [int](($payloadLines | Measure-Object -Property Length -Sum).Sum) + (2 * $payloadLines.Count) if ($payloadLines.Count -gt 8 -or $charCount -gt 1048576) {{ throw "remote_bootstrap_input_limit_exceeded" }} $payload = [string]::Join("", $payloadLines) $compressed = [Convert]::FromBase64String(($payload -replace '\s', '')) $inputStream = New-Object IO.MemoryStream(,$compressed) $gzip = New-Object IO.Compression.GzipStream($inputStream, [IO.Compression.CompressionMode]::Decompress) $reader = New-Object IO.StreamReader($gzip, [Text.Encoding]::UTF8) try {{ $inputText = $reader.ReadToEnd() }} finally {{ $reader.Dispose() $gzip.Dispose() $inputStream.Dispose() }} & ([ScriptBlock]::Create($inputText))''' encoded = base64.b64encode(decoder.encode("utf-16le")).decode("ascii") print( "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass " f"-EncodedCommand {encoded}" ) PY )" readonly REMOTE_CLEANUP_COMMAND="$(python3 - \ "${REMOTE_TRANSPORT_PATH_WINDOWS}" <<'PY' from __future__ import annotations import base64 import sys path = sys.argv[1].replace("'", "''") script = rf'''$ErrorActionPreference = "Stop" $payloadPath = '{path}' if (Test-Path -LiteralPath $payloadPath) {{ Remove-Item -LiteralPath $payloadPath -Force }} if (Test-Path -LiteralPath $payloadPath) {{ throw "remote_transport_payload_cleanup_failed" }}''' encoded = base64.b64encode(script.encode("utf-16le")).decode("ascii") print( "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass " f"-EncodedCommand {encoded}" ) PY )" cleanup_remote_payload() { timeout --signal=TERM --kill-after=5 30s \ ssh "${SSH_OPTIONS[@]}" "${TARGET}" "${REMOTE_CLEANUP_COMMAND}" /dev/null 2>&1 } if [[ "${MODE}" == "check" ]]; then set +e timeout --signal=TERM --kill-after=10 "${REMOTE_EXECUTION_TIMEOUT_SECONDS}s" \ ssh "${SSH_OPTIONS[@]}" "${TARGET}" "${REMOTE_CHECK_COMMAND}" &2 exit "${prepare_status}" fi set +e timeout --signal=TERM --kill-after=10 120s \ scp "${SCP_OPTIONS[@]}" "${BOOTSTRAP_PAYLOAD_PATH}" \ "${TARGET}:${REMOTE_TRANSPORT_PATH_SCP}" copy_status=$? set -e if [[ "${copy_status}" -ne 0 ]]; then cleanup_remote_payload || true printf 'agent99_transport_error=ephemeral_payload_copy_failed\n' >&2 exit "${copy_status}" fi set +e timeout --signal=TERM --kill-after=10 "${REMOTE_EXECUTION_TIMEOUT_SECONDS}s" \ ssh "${SSH_OPTIONS[@]}" "${TARGET}" "${REMOTE_FILE_COMMAND}" &2 if [[ "${status}" -eq 0 ]]; then exit 74 fi fi exit "${status}"