Files
isphere-ai-bridge/scripts/verify-login-reachability-probe-package.ps1
2026-07-12 14:08:25 +08:00

252 lines
11 KiB
PowerShell

param(
[string]$OutputDir = "runs/login-reachability-probe-package"
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
$packageScript = Join-Path $repo "scripts\package-login-reachability-probe.ps1"
if (-not (Test-Path -LiteralPath $packageScript)) {
throw "missing package script: $packageScript"
}
$packageRoot = Join-Path $repo $OutputDir
$zipPath = "$packageRoot.zip"
if (Test-Path -LiteralPath $packageRoot) {
Remove-Item -LiteralPath $packageRoot -Recurse -Force
}
if (Test-Path -LiteralPath $zipPath) {
Remove-Item -LiteralPath $zipPath -Force
}
& powershell -NoProfile -ExecutionPolicy Bypass -File $packageScript -OutputDir $OutputDir
if ($LASTEXITCODE -ne 0) {
throw "package-login-reachability-probe.ps1 failed with exit code $LASTEXITCODE"
}
$requiredFiles = @(
"README.txt",
"OPERATOR-STEPS.md",
"TODO-COVERAGE.md",
"EXPECTED-RETURN-FILES.txt",
"LOGIN-REACHABILITY-INPUTS.template.json",
"LOGIN-REACHABILITY-INPUTS.schema.json",
"LOGIN-REACHABILITY-PACKAGE-MANIFEST.json",
"RUN-LOGIN-REACHABILITY-SUITE.bat",
"00-prepare-inputs.bat",
"01-run-before-recorder.bat",
"02-run-after-text-recorder.bat",
"03-run-after-file-recorder.bat",
"04-create-return-zip.bat",
"CREATE-RETURN-ZIP.ps1",
"compute-text-hash.ps1",
"compute-file-hash.ps1",
"optional-run-capability-smoke.bat",
"docs\login-reachability-validation-items.md",
"docs\send-upload-deep-dive.md",
"tools\isphere-capability-smoke.exe",
"recorder\ISphereLiveProbeRecorder.exe",
"recorder\variants\ISphereLiveProbeRecorder-x86.exe"
)
foreach ($relative in $requiredFiles) {
$path = Join-Path $packageRoot $relative
if (-not (Test-Path -LiteralPath $path)) {
throw "missing package file: $relative"
}
}
$instructionText = @(
Get-Content -LiteralPath (Join-Path $packageRoot "README.txt") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "OPERATOR-STEPS.md") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "TODO-COVERAGE.md") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "EXPECTED-RETURN-FILES.txt") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.template.json") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "LOGIN-REACHABILITY-PACKAGE-MANIFEST.json") -Raw
) -join "`n"
foreach ($needle in @(
"LOCAL_LOGIN_UNAVAILABLE",
"ONLINE_LOGIN_REQUIRED",
"NO_AUTOMATIC_SEND",
"RUN-LOGIN-REACHABILITY-SUITE.bat",
"LOGIN-REACHABILITY-OUTPUT.json",
"run",
"targets",
"runtime",
"reachability",
"server_auth",
"snapshots",
"attempts",
"failures",
"correlation",
"content_sha256",
"file_sha256",
"duplicate_second_send_attempted",
"duplicate_second_file_send_attempted",
"production_send_enabled",
"production_file_send_enabled",
"runtime_observations",
"group_probe",
"fallback_a_route",
"TODO-COVERAGE",
"backup_only"
)) {
if ($instructionText -notmatch [regex]::Escape($needle)) {
throw "package instructions missing required phrase: $needle"
}
}
if (-not (Test-Path -LiteralPath $zipPath)) {
throw "missing package zip: $zipPath"
}
$inputsTemplate = Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.template.json"
$inputsPath = Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.json"
$inputs = Get-Content -LiteralPath $inputsTemplate -Raw | ConvertFrom-Json
$inputs.run.operator_confirmed_logged_in = $true
$inputs.run.operator_started_at_local = "2026-07-13T09:00:00+08:00"
$inputs.run.operator_finished_at_local = "2026-07-13T09:05:00+08:00"
$inputs.run.before_recorder_present = $true
$inputs.run.one_shot_text_enabled = $true
$inputs.run.one_shot_file_enabled = $true
$inputs.run.one_text_send_only_confirmed = $true
$inputs.run.one_file_send_only_confirmed = $true
$inputs.targets.direct_jid = "test-direct@example.invalid"
$inputs.targets.group_jid = "test-group@example.invalid"
$inputs.targets.target_selection_source = "verify-script"
$inputs.targets.self_send_or_sandbox_account_confirmed = $true
$inputs.runtime_observations.app_context_manager_reachable = $true
$inputs.runtime_observations.message_scheduling_reachable = $true
$inputs.runtime_observations.chat_xmpp_authenticated = $true
$inputs.runtime_observations.target_jid_mapping_observed = $true
$inputs.runtime_observations.file_upload_para_observed = $true
$inputs.runtime_observations.ifile_transfer_reachable = $true
$inputs.runtime_observations.file_upload_result_file_id_observed = $true
$inputs.runtime_observations.send_file_message_finalization_observed = $true
$inputs.runtime_observations.notes = "synthetic runtime observations"
$inputs.text_attempt.content_sha256 = ("a" * 64)
$inputs.text_attempt.content_length = 16
$inputs.text_attempt.operator_clicked_send_at_local = "2026-07-13T09:01:00+08:00"
$inputs.text_attempt.after_recorder_present = $true
$inputs.text_attempt.success_ack_or_sent_record_present = $true
$inputs.text_attempt.success_ack_or_sent_record = "synthetic sent-record ack for verify script"
$inputs.text_attempt.duplicate_second_send_attempted = $false
$inputs.file_attempt.allowed_dir = "C:\verify"
$inputs.file_attempt.sandbox_file_path = "C:\verify\small.txt"
$inputs.file_attempt.file_sha256 = ("b" * 64)
$inputs.file_attempt.file_size_bytes = 12
$inputs.file_attempt.operator_clicked_send_file_at_local = "2026-07-13T09:03:00+08:00"
$inputs.file_attempt.after_recorder_present = $true
$inputs.file_attempt.file_upload_or_sent_record_present = $true
$inputs.file_attempt.file_upload_or_sent_record = "synthetic file sent-record ack for verify script"
$inputs.file_attempt.duplicate_second_file_send_attempted = $false
$inputs.group_probe.enabled = $true
$inputs.group_probe.group_jid = "test-group@example.invalid"
$inputs.group_probe.chatroom_branch_observed = $true
$inputs.group_probe.speech_permission_state = "allowed"
$inputs.group_probe.upload_permission_state = "allowed"
$inputs.fallback_a_route.enabled_if_b_route_fails = $true
$inputs.fallback_a_route.hwnd = "0x1234"
$inputs.fallback_a_route.rtbSendMessage_present = $true
$inputs.fallback_a_route.btnSend_present = $true
$inputs.fallback_a_route.btnSendFile_or_file_menu_present = $true
$inputs.fallback_a_route.uia_or_screenshot_ref = "synthetic fallback evidence"
$inputs.sent_record_source.source_type = "synthetic"
$inputs.sent_record_source.source_path_or_ref = "verify-script"
$inputs.sent_record_source.before_count = "1"
$inputs.sent_record_source.after_count = "3"
$inputs.sent_record_source.ack_or_ref_id = "verify-ack"
$inputs.sent_record_source.correlation_notes = "synthetic verification only"
$inputs | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $inputsPath -Encoding UTF8
$beforeProbeDir = Join-Path $packageRoot "return-evidence\before\isphere-live-probe-verify"
$afterTextDir = Join-Path $packageRoot "return-evidence\after-text\isphere-live-probe-verify"
$afterFileDir = Join-Path $packageRoot "return-evidence\after-file\isphere-live-probe-verify"
New-Item -ItemType Directory -Force -Path $beforeProbeDir, $afterTextDir, $afterFileDir | Out-Null
@'
{
"probe_mode": "verify",
"target_count": 1,
"host": { "is_64_bit_os": true, "is_64_bit_process": false, "machine_name": "VERIFY" },
"targets": [
{
"pid": 1234,
"process_name": "IMPlatformClient",
"bitness": "x86",
"assembly_presence": {
"IMPlatformClient.exe": true,
"smack.dll": true,
"IMPP.Interface.dll": true,
"IMPP.Service.dll": true,
"IMPP.ServiceBase.dll": true
}
}
]
}
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "probe_client_runtime.json") -Encoding UTF8
@'
{
"entrypoints": [
{ "id": "text_high_level_by_jid", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "text_message_scheduler", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "text_wire_chat_send", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "file_service_upload", "capability": "send_file", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "file_wire_message", "capability": "send_file", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" }
]
}
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "send_entrypoints_preflight.json") -Encoding UTF8
@'
{ "tcp": { "connection_count": 1, "connections": [ { "state": "ESTABLISHED", "remote_port": 5222 } ] } }
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "network_inventory.json") -Encoding UTF8
@'
{ "target_process_seen": true, "initial_route_hint": "B_ROUTE_PROMISING" }
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "feasibility_summary.json") -Encoding UTF8
"after text synthetic evidence" | Set-Content -LiteralPath (Join-Path $afterTextDir "dummy.txt") -Encoding UTF8
"after file synthetic evidence" | Set-Content -LiteralPath (Join-Path $afterFileDir "dummy.txt") -Encoding UTF8
Push-Location $packageRoot
try {
$returnOutput = & powershell -NoProfile -ExecutionPolicy Bypass -File ".\CREATE-RETURN-ZIP.ps1" 2>&1
$returnExit = $LASTEXITCODE
}
finally {
Pop-Location
}
if ($returnExit -ne 0) {
throw "CREATE-RETURN-ZIP.ps1 synthetic verification failed exit=$returnExit output=$($returnOutput -join "`n")"
}
$outputJson = Join-Path $packageRoot "LOGIN-REACHABILITY-OUTPUT.json"
if (-not (Test-Path -LiteralPath $outputJson)) {
throw "missing generated LOGIN-REACHABILITY-OUTPUT.json"
}
$output = Get-Content -LiteralPath $outputJson -Raw | ConvertFrom-Json
foreach ($section in @("run", "targets", "runtime", "reachability", "server_auth", "snapshots", "attempts", "failures", "correlation")) {
if ($null -eq $output.PSObject.Properties[$section]) {
throw "LOGIN-REACHABILITY-OUTPUT.json missing section: $section"
}
}
if ($output.run.validation_ok -ne $true) {
throw "synthetic LOGIN-REACHABILITY-OUTPUT.json should have validation_ok=true"
}
[ordered]@{
ok = $true
package_dir = (Resolve-Path -LiteralPath $packageRoot).Path
zip = (Resolve-Path -LiteralPath $zipPath).Path
required_file_count = $requiredFiles.Count
synthetic_return_verified = $true
online_login_required = $true
no_automatic_send = $true
production_send_enabled = $false
production_file_send_enabled = $false
} | ConvertTo-Json -Depth 6 -Compress