feat: add bounded private acquisition transport

This commit is contained in:
Codex 2026-10-17 16:23:01 +02:00
parent 805691a71b
commit 845da21a9f
3 changed files with 56 additions and 0 deletions

View file

@ -32,5 +32,10 @@ python -m unittest discover -s tests -v
python scripts/check_public_repo.py . python scripts/check_public_repo.py .
``` ```
`scripts/materialize_private_drive_files.ps1` is the bounded transport used by
the acquisition workflow. It accepts authenticated download references over
standard input, rejects path traversal, and verifies byte sizes before files
enter PrivateStash. It never prints download credentials.
No project license has been selected yet. Until that decision is recorded, No project license has been selected yet. Until that decision is recorded,
the contents are not offered under an open-source license. the contents are not offered under an open-source license.

View file

@ -31,3 +31,7 @@ project artifact is created, edited, renamed, or reorganized there.
4. Create a sanitized derivative in the public repository. 4. Create a sanitized derivative in the public repository.
5. Run automated guards and manually review the staged diff. 5. Run automated guards and manually review the staged diff.
6. Commit and push the private evidence before the public claim that cites it. 6. Commit and push the private evidence before the public claim that cites it.
During Drive acquisition, authenticated download references are ephemeral and
must be passed to the bounded materializer over standard input. They must not be
written to scripts, manifests, command history, or Git.

View file

@ -0,0 +1,47 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$Root
)
$ErrorActionPreference = 'Stop'
$rootPath = (Resolve-Path -LiteralPath $Root).Path
$rootPrefix = $rootPath.TrimEnd([IO.Path]::DirectorySeparatorChar) + [IO.Path]::DirectorySeparatorChar
while (($line = [Console]::In.ReadLine()) -ne $null) {
if ($line -eq '__END__') {
break
}
if ([string]::IsNullOrWhiteSpace($line)) {
continue
}
$item = $line | ConvertFrom-Json
if (-not $item.relative_path -or -not $item.download_url) {
throw 'Each input line must contain relative_path and download_url.'
}
$relativePath = $item.relative_path.Replace('/', [IO.Path]::DirectorySeparatorChar)
$destination = [IO.Path]::GetFullPath((Join-Path $rootPath $relativePath))
if (-not $destination.StartsWith($rootPrefix, [StringComparison]::OrdinalIgnoreCase)) {
throw "Refusing path outside acquisition root: $($item.relative_path)"
}
$parent = Split-Path -Parent $destination
New-Item -ItemType Directory -Path $parent -Force | Out-Null
Invoke-WebRequest -UseBasicParsing -Uri $item.download_url -OutFile $destination
$actualSize = (Get-Item -LiteralPath $destination).Length
if ($null -ne $item.expected_size -and $actualSize -ne [long]$item.expected_size) {
throw "Size mismatch for $($item.relative_path): expected $($item.expected_size), got $actualSize"
}
if ($item.expected_sha256) {
$actualHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $destination).Hash.ToLowerInvariant()
if ($actualHash -ne $item.expected_sha256.ToLowerInvariant()) {
throw "SHA-256 mismatch for $($item.relative_path)"
}
}
Write-Output ("OK`t{0}`t{1}" -f $actualSize, $item.relative_path)
}