225 lines
9.5 KiB
PowerShell
225 lines
9.5 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",
|
|
"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 "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",
|
|
"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.target_selection_source = "verify-script"
|
|
$inputs.targets.self_send_or_sandbox_account_confirmed = $true
|
|
$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.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
|