feat: expand merged chat records directly from read-only databases
Add db merged with exact account/chat/local-ID selection and shard ambiguity checks. Preserve Int64 composite message types and parse bounded, DTD-free embedded record XML, including duplicate messages and source metadata. Revalidate cached keys against current page-1 HMAC; replace the SQL write probe with sqlite3_db_readonly. Core tests: 129 passed. Windows Session 0 database validation: 5/5; all 16 text/sender/source-ID/timestamp entries matched independent XML parsing. Read-only UI baseline: 3/3; zero sends.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Executable,
|
||||
[Parameter(Mandatory=$true)][string]$OutputDirectory,
|
||||
[Parameter(Mandatory=$true)][string]$Account,
|
||||
[string]$ChatId='filehelper',
|
||||
[Parameter(Mandatory=$true)][long]$LocalId,
|
||||
[Parameter(Mandatory=$true)][int]$ExpectedCount
|
||||
)
|
||||
$ErrorActionPreference='Stop'
|
||||
$exe=(Resolve-Path $Executable).Path
|
||||
if(Test-Path $OutputDirectory){throw 'Use a fresh evidence directory.'}
|
||||
$out=(New-Item -ItemType Directory $OutputDirectory).FullName
|
||||
$checks=New-Object System.Collections.Generic.List[object]
|
||||
function Check([string]$Name,[string[]]$Arguments,[int]$ExpectedExit=0){
|
||||
$raw=(& $exe @Arguments 2> "$out\$Name.stderr.txt" | Out-String)
|
||||
$code=$LASTEXITCODE
|
||||
$raw | Set-Content "$out\$Name.json" -Encoding UTF8
|
||||
$checks.Add(@{Stage=$Name;ExitCode=$code;ExpectedExit=$ExpectedExit})
|
||||
if($code -ne $ExpectedExit){throw "$Name returned unexpected exit code."}
|
||||
return ($raw | ConvertFrom-Json)
|
||||
}
|
||||
try {
|
||||
$default=Check 'merged-default' @('db','merged','--account',$Account,'--chat',$ChatId,'--local-id',"$LocalId",'--timeout','60')
|
||||
if($default.record.count -ne $ExpectedCount){throw 'Unexpected record count.'}
|
||||
if($null -ne $default.record.title -or $null -ne $default.record.description -or @($default.record.messages | Where-Object {$null -ne $_.text -or $null -ne $_.senderName}).Count){throw 'Default output leaked record content.'}
|
||||
$full=Check 'merged-content.private' @('db','merged','--account',$Account,'--chat',$ChatId,'--local-id',"$LocalId",'--include-content','--timeout','60')
|
||||
if($full.record.count -ne $ExpectedCount -or $full.parent.LocalId -ne $LocalId){throw 'Selected record mismatch.'}
|
||||
if(@($full.record.messages | Where-Object {$_.dataType -ne 1 -or $null -eq $_.text -or !$_.senderName -or !$_.timestamp -or !$_.sourceServerId}).Count){throw 'Expected complete text-message metadata in this fixture.'}
|
||||
if(@($full.record.messages.path | Select-Object -Unique).Count -ne $ExpectedCount){throw 'Message paths are not unique.'}
|
||||
$metadata=Check 'database-readonly' @('db','query','--account',$Account,'--database',$full.database,'--timeout','60')
|
||||
if(!$metadata.metadata.WritesRejected){throw 'Database is not reported read-only.'}
|
||||
$invalid=Check 'invalid-id' @('db','merged','--account',$Account,'--chat',$ChatId,'--local-id','0','--timeout','30') 1
|
||||
if($invalid.error -ne 'InvalidArgument'){throw 'Wrong invalid-ID error.'}
|
||||
$missing=Check 'missing-id' @('db','merged','--account',$Account,'--chat',$ChatId,'--local-id','9223372036854775807','--timeout','60') 1
|
||||
if($missing.error -ne 'ControlNotFound'){throw 'Wrong missing-ID error.'}
|
||||
} catch {
|
||||
@{Message=$_.Exception.Message;Line=$_.InvocationInfo.ScriptLineNumber} | ConvertTo-Json | Set-Content "$out\error.json" -Encoding UTF8
|
||||
} finally {
|
||||
$success=($checks.Count -eq 5 -and @($checks | Where-Object {$_.ExitCode -ne $_.ExpectedExit}).Count -eq 0 -and !(Test-Path "$out\error.json"))
|
||||
@{Success=$success;Checks=@($checks.ToArray());ProcessSessionId=[Diagnostics.Process]::GetCurrentProcess().SessionId;RecordCount=$ExpectedCount;SendsAttempted=0;BinarySha256=(Get-FileHash $exe -Algorithm SHA256).Hash} |
|
||||
ConvertTo-Json -Depth 6 | Set-Content "$out\summary.json" -Encoding UTF8
|
||||
}
|
||||
if(!$success){exit 1}
|
||||
Reference in New Issue
Block a user