Ka-Note/ka-note/scripts/unlock.ps1

118 lines
3.7 KiB
PowerShell

<#
.SYNOPSIS
Releases the AI lock without uploading data.
Reads the lock token from <repo-root>/work/kai-bundle.json by default.
.PARAMETER LockToken
Override lock token directly.
.PARAMETER BundleFile
Override bundle file to read token from.
.PARAMETER Prod
Target production server.
.PARAMETER Token
Bearer token for prod auth. Falls back to $env:KA_NOTE_TOKEN.
.EXAMPLE
.\unlock.ps1
.\unlock.ps1 -LockToken "abc-123"
.\unlock.ps1 -Prod -Token eyJ...
#>
param(
[string]$LockToken,
[string]$BundleFile,
[switch]$Prod,
[string]$Token
)
$ErrorActionPreference = 'Stop'
# --- Helpers -----------------------------------------------------------------
function Write-Header([string]$Text) {
Write-Host ""
Write-Host " $Text" -ForegroundColor White
Write-Host (" " + ("-" * $Text.Length)) -ForegroundColor DarkGray
}
function Write-KV([string]$Key, [string]$Value, [string]$Color = "Gray") {
Write-Host (" {0,-14} " -f $Key) -NoNewline -ForegroundColor DarkGray
Write-Host $Value -ForegroundColor $Color
}
function Write-Ok([string]$Msg) { Write-Host " [OK] $Msg" -ForegroundColor Green }
function Write-Warn([string]$Msg) { Write-Host " [!!] $Msg" -ForegroundColor Yellow }
function Write-Err([string]$Msg) { Write-Host " [!!] $Msg" -ForegroundColor Red }
function Write-Hint([string]$Msg) { Write-Host " -> $Msg" -ForegroundColor DarkCyan }
# --- Resolve lock token ------------------------------------------------------
$RepoRoot = Resolve-Path "$PSScriptRoot\..\.."
$WorkDir = Join-Path $RepoRoot "work"
# Support legacy BundleFile param and new manifest.json
if (-not $BundleFile) { $BundleFile = Join-Path $WorkDir "manifest.json" }
if (-not $LockToken) {
if (Test-Path $BundleFile) {
$BundleContent = Get-Content $BundleFile -Raw -Encoding UTF8 | ConvertFrom-Json
# manifest.json has lockToken directly; legacy kai-bundle.json has manifest.lockToken
$LockToken = if ($BundleContent.lockToken) { $BundleContent.lockToken } else { $BundleContent.manifest.lockToken }
$TokenSource = $BundleFile
}
if (-not $LockToken) {
Write-Err "No lock token found. Pass -LockToken or run .\download.ps1 first."
exit 1
}
}
# --- Server ------------------------------------------------------------------
if ($Prod) {
$BaseUrl = "https://ka-note.azurewebsites.net"
$BearerToken = if ($Token) { $Token } elseif ($env:KA_NOTE_TOKEN) { $env:KA_NOTE_TOKEN } else {
Write-Host " Acquiring token via MSAL..." -ForegroundColor DarkGray
& "$PSScriptRoot\get-token.ps1"
}
if (-not $BearerToken) {
Write-Err "Failed to acquire a Bearer token."
exit 1
}
$Headers = @{ Authorization = "Bearer $BearerToken"; "Content-Type" = "application/json" }
$Env = "prod"
} else {
$BaseUrl = "http://localhost:3001"
$Headers = @{ "Content-Type" = "application/json" }
$Env = "dev"
}
Write-Header "Ka-Note AI Unlock"
Write-KV "server" $BaseUrl $(if ($Prod) { "Yellow" } else { "Cyan" })
Write-KV "mode" $Env
Write-KV "lock" $LockToken "Yellow"
if ($TokenSource) { Write-KV "from" $TokenSource }
Write-Host ""
Write-Host " Unlocking..." -ForegroundColor DarkGray
$Json = @{ lockToken = $LockToken } | ConvertTo-Json -Compress
try {
Invoke-WebRequest -Uri "$BaseUrl/api/ai/unlock" `
-Method POST -Headers $Headers -Body $Json -UseBasicParsing | Out-Null
Write-Host ""
Write-Ok "Lock released. Sync is active again."
Write-Host ""
} catch {
$StatusCode = $_.Exception.Response.StatusCode.value__
Write-Host ""
if ($StatusCode -eq 401) {
Write-Warn "401 — lock token invalid or already expired (lock may have auto-expired)."
} else {
Write-Err "HTTP $StatusCode$($_.Exception.Message)"
exit 1
}
Write-Host ""
}