Files
jiapuapp/tests/auth-tac-openapi-contract.ps1
T
2026-07-27 06:50:23 +08:00

53 lines
2.7 KiB
PowerShell

$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$apiPath = Join-Path $root 'utils/api.js'
$a01Path = Join-Path $root 'pages/auth/a01-entry.vue'
$runtimePath = Join-Path $PSScriptRoot 'auth-api-runtime-smoke.js'
$issues = New-Object System.Collections.Generic.List[string]
foreach ($path in @($apiPath, $a01Path, $runtimePath)) {
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
$issues.Add("missing authentication owner: $path")
}
}
if ($issues.Count -eq 0) {
$api = Get-Content -Raw -Encoding UTF8 -LiteralPath $apiPath
$a01 = Get-Content -Raw -Encoding UTF8 -LiteralPath $a01Path
$passwordOwner = [regex]::Match($api, '(?s)async loginWithPassword\(\{ phone, passwordHash, validToken \}.*?(?=\s+async loginWithSms)')
if (-not $passwordOwner.Success) {
$issues.Add('missing bounded password login owner')
} else {
foreach ($required in @("url: '/genealogy/app/auth/login'", "tenantId: runtimeConfig.tenantId", "grantType: 'password'", 'password: assertPasswordHash(passwordHash)', 'const normalizedValidToken = normalizeOptionalValidToken(validToken)', '...(normalizedValidToken ? { validToken: normalizedValidToken } : {})')) {
if (-not $passwordOwner.Value.Contains($required)) { $issues.Add("password login owner missing: $required") }
}
if ($passwordOwner.Value.Contains('authPayload(')) {
$issues.Add('password login must not put clientId in the body')
}
}
foreach ($required in @('const preparePasswordLogin = async () =>', 'appApi.loginWithPassword', 'TAC')) {
if (-not $a01.Contains($required)) { $issues.Add("A01 missing password TAC precondition: $required") }
}
$smsOwner = [regex]::Match($api, '(?s)async sendSmsCode\(\{ operationCode, phone, validToken \}.*?(?=\s+async loginWithPassword)')
if (-not $smsOwner.Success -or -not $smsOwner.Value.Contains('const normalizedValidToken = normalizeOptionalValidToken(validToken)') -or -not $smsOwner.Value.Contains('...(normalizedValidToken ? { validToken: normalizedValidToken } : {})')) {
$issues.Add('SMS owner must remain the sole validToken consumer and omit it only when the server policy closes TAC')
}
}
if ($issues.Count -eq 0) {
$runtimeOutput = @(& node $runtimePath 2>&1)
if ($LASTEXITCODE -ne 0 -or 'AUTH-API-RUNTIME-SMOKE PASS' -notin $runtimeOutput) {
$issues.Add("password and SMS wire runtime smoke failed: $($runtimeOutput -join ' | ')")
}
}
if ($issues.Count -gt 0) {
Write-Output 'AUTH-TAC-OPENAPI-CONTRACT BLOCKED'
foreach ($issue in $issues) { Write-Output "- $issue" }
Write-Output '- Password login and SMS operations send a validToken only after the server marks that operation as verification-required.'
exit 1
}
Write-Output 'AUTH-TAC-OPENAPI-CONTRACT PASS'