Skip to content

Commit 1fc316f

Browse files
committed
fix: replace non-ASCII characters in PowerShell deploy scripts
PowerShell 5.1 reads UTF-8-without-BOM files as CP1252 on Windows. The em dash (U+2014, UTF-8: E2 80 94) has its third byte (0x94) mapped to the right double quotation mark (U+201D) in CP1252, which prematurely closes string literals in Write-Host calls. Replace all em dashes and other non-ASCII characters with ASCII equivalents in Validation-Helpers.psm1, manage_api_keys.ps1, and windows_setup.ps1. Files verified parse-clean with PS 5.1 Parser::ParseFile.
1 parent cc2b51e commit 1fc316f

File tree

3 files changed

+41
-41
lines changed

3 files changed

+41
-41
lines changed

deploy/Validation-Helpers.psm1

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function Test-CourtListenerToken {
4444
If specified, suppress output and return only boolean.
4545
4646
.OUTPUTS
47-
Boolean $true if valid, $false if invalid.
47+
Boolean - $true if valid, $false if invalid.
4848
#>
4949
[CmdletBinding()]
5050
[OutputType([bool])]
@@ -110,7 +110,7 @@ function Test-OpenAiApiKey {
110110
If specified, suppress output and return only boolean.
111111
112112
.OUTPUTS
113-
Boolean $true if valid or empty, $false if provided but invalid.
113+
Boolean - $true if valid or empty, $false if provided but invalid.
114114
#>
115115
[CmdletBinding()]
116116
[OutputType([bool])]
@@ -123,11 +123,11 @@ function Test-OpenAiApiKey {
123123
)
124124

125125
if ([string]::IsNullOrWhiteSpace($ApiKey)) {
126-
if (-not $Silent) { Write-Host "[INFO] OpenAI/Ollama API key is optional skipping validation" -ForegroundColor Cyan }
126+
if (-not $Silent) { Write-Host "[INFO] OpenAI/Ollama API key is optional - skipping validation" -ForegroundColor Cyan }
127127
return $true
128128
}
129129

130-
# Accept Ollama local endpoint key values Ollama ignores the key entirely
130+
# Accept Ollama local endpoint key values - Ollama ignores the key entirely
131131
# Matches: "ollama", "ollama:modelname", "OLLAMA", etc.
132132
if ($ApiKey -match '^ollama(:[a-zA-Z0-9._/-]+)?$') {
133133
if (-not $Silent) {
@@ -185,7 +185,7 @@ function Test-MistralApiKey {
185185
If specified, suppress output and return only boolean.
186186
187187
.OUTPUTS
188-
Boolean $true if valid or empty, $false if provided but invalid.
188+
Boolean - $true if valid or empty, $false if provided but invalid.
189189
#>
190190
[CmdletBinding()]
191191
[OutputType([bool])]
@@ -198,7 +198,7 @@ function Test-MistralApiKey {
198198
)
199199

200200
if ([string]::IsNullOrWhiteSpace($ApiKey)) {
201-
if (-not $Silent) { Write-Host "[INFO] Mistral API key is optional skipping validation" -ForegroundColor Cyan }
201+
if (-not $Silent) { Write-Host "[INFO] Mistral API key is optional - skipping validation" -ForegroundColor Cyan }
202202
return $true
203203
}
204204

@@ -247,7 +247,7 @@ function Test-PlaceholderPattern {
247247
If specified, suppress output and return only boolean.
248248
249249
.OUTPUTS
250-
Boolean $true if placeholder detected (invalid), $false if clean.
250+
Boolean - $true if placeholder detected (invalid), $false if clean.
251251
#>
252252
[CmdletBinding()]
253253
[OutputType([bool])]
@@ -272,7 +272,7 @@ function Test-PlaceholderPattern {
272272
Write-Host "[ERROR] Detected placeholder pattern in $KeyType key: '$pattern'" -ForegroundColor Red
273273
Write-Host " Please use your actual key, not a placeholder" -ForegroundColor Yellow
274274
}
275-
return $true # Placeholder found caller should treat as invalid
275+
return $true # Placeholder found - caller should treat as invalid
276276
}
277277
}
278278

@@ -302,7 +302,7 @@ function Test-PathSecurity {
302302
If specified, suppress output and return only boolean.
303303
304304
.OUTPUTS
305-
Boolean $true if safe, $false if rejected.
305+
Boolean - $true if safe, $false if rejected.
306306
#>
307307
[CmdletBinding()]
308308
[OutputType([bool])]
@@ -320,7 +320,7 @@ function Test-PathSecurity {
320320
if ($Path -match '\.\.') {
321321
if (-not $Silent) {
322322
Write-Host "[ERROR] $PathName contains path traversal (..): $Path" -ForegroundColor Red
323-
Write-Host " Path traversal is a security risk rejected" -ForegroundColor Red
323+
Write-Host " Path traversal is a security risk - rejected" -ForegroundColor Red
324324
}
325325
return $false
326326
}
@@ -365,7 +365,7 @@ function New-SecureSecret {
365365
Number of random bytes (default 32, yields a 44-char base64 string).
366366
367367
.OUTPUTS
368-
String Base64-encoded secure random secret.
368+
String - Base64-encoded secure random secret.
369369
#>
370370
[CmdletBinding()]
371371
[OutputType([string])]
@@ -400,7 +400,7 @@ function Read-ApiKeySecure {
400400
The prompt text to display.
401401
402402
.OUTPUTS
403-
String The entered key in plaintext.
403+
String - The entered key in plaintext.
404404
#>
405405
[CmdletBinding()]
406406
[OutputType([string])]
@@ -429,7 +429,7 @@ function Read-CourtListenerTokenWithValidation {
429429
Maximum number of attempts before giving up (default 3).
430430
431431
.OUTPUTS
432-
String Valid token, or $null if all attempts failed.
432+
String - Valid token, or $null if all attempts failed.
433433
#>
434434
[CmdletBinding()]
435435
[OutputType([string])]
@@ -457,7 +457,7 @@ function Read-CourtListenerTokenWithValidation {
457457
}
458458
else {
459459
if ($attempt -lt $MaxAttempts) {
460-
Write-Host "[WARN] Attempt $attempt of $MaxAttempts please try again" -ForegroundColor Yellow
460+
Write-Host "[WARN] Attempt $attempt of $MaxAttempts - please try again" -ForegroundColor Yellow
461461
Write-Host "[INFO] Format: 40 lowercase hex characters (a-f, 0-9)" -ForegroundColor Cyan
462462
}
463463
}
@@ -473,13 +473,13 @@ function Read-OpenAiApiKeyWithValidation {
473473
Prompts for an OpenAI API key with validation retry loop (optional key).
474474
475475
.DESCRIPTION
476-
Press Enter to skip OpenAI is optional for this MCP.
476+
Press Enter to skip - OpenAI is optional for this MCP.
477477
478478
.PARAMETER MaxAttempts
479479
Maximum number of attempts before giving up (default 3).
480480
481481
.OUTPUTS
482-
String Valid key, empty string if skipped, or $null if all attempts failed.
482+
String - Valid key, empty string if skipped, or $null if all attempts failed.
483483
#>
484484
[CmdletBinding()]
485485
[OutputType([string])]
@@ -510,7 +510,7 @@ function Read-OpenAiApiKeyWithValidation {
510510
}
511511
else {
512512
if ($attempt -lt $MaxAttempts) {
513-
Write-Host "[WARN] Attempt $attempt of $MaxAttempts please try again" -ForegroundColor Yellow
513+
Write-Host "[WARN] Attempt $attempt of $MaxAttempts - please try again" -ForegroundColor Yellow
514514
Write-Host "[INFO] Format: starts with 'sk-' (OpenAI) or enter 'ollama' for local Ollama endpoint" -ForegroundColor Cyan
515515
}
516516
}
@@ -526,13 +526,13 @@ function Read-MistralApiKeyWithValidation {
526526
Prompts for a Mistral API key with validation retry loop (optional key).
527527
528528
.DESCRIPTION
529-
Press Enter to skip Mistral is optional for this MCP.
529+
Press Enter to skip - Mistral is optional for this MCP.
530530
531531
.PARAMETER MaxAttempts
532532
Maximum number of attempts before giving up (default 3).
533533
534534
.OUTPUTS
535-
String Valid key, empty string if skipped, or $null if all attempts failed.
535+
String - Valid key, empty string if skipped, or $null if all attempts failed.
536536
#>
537537
[CmdletBinding()]
538538
[OutputType([string])]
@@ -563,7 +563,7 @@ function Read-MistralApiKeyWithValidation {
563563
}
564564
else {
565565
if ($attempt -lt $MaxAttempts) {
566-
Write-Host "[WARN] Attempt $attempt of $MaxAttempts please try again" -ForegroundColor Yellow
566+
Write-Host "[WARN] Attempt $attempt of $MaxAttempts - please try again" -ForegroundColor Yellow
567567
Write-Host "[INFO] Format: 32 alphanumeric characters (a-z, A-Z, 0-9)" -ForegroundColor Cyan
568568
}
569569
}
@@ -586,7 +586,7 @@ function Show-ApiKeyRequirements {
586586
param()
587587

588588
Write-Host ""
589-
Write-Host "API Key Requirements CourtListener Citation Validation MCP" -ForegroundColor Cyan
589+
Write-Host "API Key Requirements - CourtListener Citation Validation MCP" -ForegroundColor Cyan
590590
Write-Host "==============================================================" -ForegroundColor Cyan
591591
Write-Host ""
592592
Write-Host "CourtListener API Token:" -ForegroundColor White
@@ -625,7 +625,7 @@ function Hide-ApiKey {
625625
Number of characters to show at the end (default 5).
626626
627627
.OUTPUTS
628-
String Masked key, e.g. "***...abcde".
628+
String - Masked key, e.g. "***...abcde".
629629
#>
630630
[CmdletBinding()]
631631
[OutputType([string])]

deploy/manage_api_keys.ps1

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Mistral API key (optional, 32-char alphanumeric)
1111
1212
Storage:
13-
- CourtListener: Windows Credential Manager (primary) DPAPI file fallback (~/.courtlistener_api_token)
13+
- CourtListener: Windows Credential Manager (primary) -> DPAPI file fallback (~/.courtlistener_api_token)
1414
- OpenAI: DPAPI encrypted file (~/.openai_api_key)
1515
- Mistral: DPAPI encrypted file (~/.mistral_api_key)
1616
@@ -96,7 +96,7 @@ function Set-DpapiKeyToFile {
9696
}
9797

9898
# ============================================================================
99-
# CourtListener Token Python-backed secure storage
99+
# CourtListener Token - Python-backed secure storage
100100
# ============================================================================
101101

102102
function Get-CourtListenerToken {
@@ -191,7 +191,7 @@ function Remove-CourtListenerToken {
191191
}
192192

193193
# ============================================================================
194-
# Status Check all three keys
194+
# Status Check - all three keys
195195
# ============================================================================
196196

197197
function Show-KeyStatus {
@@ -259,7 +259,7 @@ function Show-KeyStatus {
259259
}
260260

261261
# ============================================================================
262-
# Live API Test CourtListener only (others are validated by format only)
262+
# Live API Test - CourtListener only (others are validated by format only)
263263
# ============================================================================
264264

265265
function Test-CourtListenerConnection {
@@ -287,7 +287,7 @@ function Test-CourtListenerConnection {
287287
catch {
288288
$statusCode = $_.Exception.Response.StatusCode.Value__
289289
if ($statusCode -eq 401) {
290-
Write-Host "[ERROR] API returned 401 Unauthorized token may be invalid or expired" -ForegroundColor Red
290+
Write-Host "[ERROR] API returned 401 Unauthorized - token may be invalid or expired" -ForegroundColor Red
291291
}
292292
elseif ($statusCode) {
293293
Write-Host "[ERROR] API returned HTTP $statusCode" -ForegroundColor Red
@@ -309,7 +309,7 @@ function Test-OpenAiKeyFormat {
309309
Write-Host "[OK] OpenAI API key format valid" -ForegroundColor Green
310310
}
311311
else {
312-
Write-Host "[!!] OpenAI API key format INVALID please update it" -ForegroundColor Red
312+
Write-Host "[!!] OpenAI API key format INVALID - please update it" -ForegroundColor Red
313313
}
314314
}
315315

@@ -324,7 +324,7 @@ function Test-MistralKeyFormat {
324324
Write-Host "[OK] Mistral API key format valid (32 chars, alphanumeric)" -ForegroundColor Green
325325
}
326326
else {
327-
Write-Host "[!!] Mistral API key format INVALID please update it" -ForegroundColor Red
327+
Write-Host "[!!] Mistral API key format INVALID - please update it" -ForegroundColor Red
328328
}
329329
}
330330

@@ -345,7 +345,7 @@ function Remove-OptionalKey {
345345
}
346346

347347
# ============================================================================
348-
# Migrate CourtListener token from DPAPI file Credential Manager
348+
# Migrate CourtListener token from DPAPI file -> Credential Manager
349349
# ============================================================================
350350

351351
function Invoke-MigrateCourtListenerToken {
@@ -355,12 +355,12 @@ function Invoke-MigrateCourtListenerToken {
355355
# Already in Credential Manager?
356356
$existing = Get-CourtListenerToken
357357
if ($existing) {
358-
Write-Host "[OK] Token already present in Credential Manager nothing to migrate" -ForegroundColor Green
358+
Write-Host "[OK] Token already present in Credential Manager - nothing to migrate" -ForegroundColor Green
359359
return
360360
}
361361

362362
if (-not (Test-Path $CL_TOKEN_PATH)) {
363-
Write-Host "[INFO] No DPAPI file found at $CL_TOKEN_PATH nothing to migrate" -ForegroundColor Yellow
363+
Write-Host "[INFO] No DPAPI file found at $CL_TOKEN_PATH - nothing to migrate" -ForegroundColor Yellow
364364
return
365365
}
366366

@@ -381,7 +381,7 @@ try:
381381
success = migrate_to_credential_manager()
382382
print('SUCCESS' if success else 'SKIPPED')
383383
except AttributeError:
384-
# Function may not exist in older versions call store_api_token with file content
384+
# Function may not exist in older versions - call store_api_token with file content
385385
from courtlistener_mcp.shared.secure_storage import get_api_token, store_api_token
386386
token = get_api_token()
387387
if token:
@@ -395,14 +395,14 @@ except Exception as e:
395395

396396
$result = & $pythonExe -c $pythonCode 2>$null | Out-String
397397
if ($result -match "SUCCESS") {
398-
Write-Host "[OK] Migration successful token now in Credential Manager" -ForegroundColor Green
398+
Write-Host "[OK] Migration successful - token now in Credential Manager" -ForegroundColor Green
399399
Write-Host " DPAPI file retained as backup: $CL_TOKEN_PATH" -ForegroundColor Gray
400400
}
401401
elseif ($result -match "SKIPPED") {
402402
Write-Host "[OK] Token already in Credential Manager" -ForegroundColor Green
403403
}
404404
elseif ($result -match "NO_TOKEN") {
405-
Write-Host "[ERROR] Could not read token from DPAPI file file may be corrupted" -ForegroundColor Red
405+
Write-Host "[ERROR] Could not read token from DPAPI file - file may be corrupted" -ForegroundColor Red
406406
}
407407
else {
408408
Write-Host "[ERROR] Migration failed: $result" -ForegroundColor Red
@@ -416,7 +416,7 @@ except Exception as e:
416416
function Main {
417417
while ($true) {
418418
Clear-Host
419-
Write-Host "CourtListener Citation MCP API Key Management" -ForegroundColor Cyan
419+
Write-Host "CourtListener Citation MCP - API Key Management" -ForegroundColor Cyan
420420
Write-Host "================================================" -ForegroundColor Cyan
421421

422422
Show-KeyStatus
@@ -427,7 +427,7 @@ function Main {
427427
Write-Host " [3] Update Mistral API key"
428428
Write-Host " [4] Test all keys"
429429
Write-Host " [5] Remove key(s)"
430-
Write-Host " [6] Migrate CourtListener token (DPAPI file Credential Manager)"
430+
Write-Host " [6] Migrate CourtListener token (DPAPI file -> Credential Manager)"
431431
Write-Host " [7] Show key format requirements"
432432
Write-Host " [8] Exit"
433433
Write-Host ""
@@ -450,7 +450,7 @@ function Main {
450450
Set-CourtListenerToken -Token $newToken | Out-Null
451451
}
452452
else {
453-
Write-Host "[INFO] Operation cancelled no valid token provided" -ForegroundColor Yellow
453+
Write-Host "[INFO] Operation cancelled - no valid token provided" -ForegroundColor Yellow
454454
}
455455

456456
Write-Host ""
@@ -474,7 +474,7 @@ function Main {
474474
Write-Host "[ERROR] Validation failed after maximum attempts" -ForegroundColor Red
475475
}
476476
else {
477-
Write-Host "[INFO] Operation cancelled no key provided" -ForegroundColor Yellow
477+
Write-Host "[INFO] Operation cancelled - no key provided" -ForegroundColor Yellow
478478
}
479479

480480
Write-Host ""
@@ -498,7 +498,7 @@ function Main {
498498
Write-Host "[ERROR] Validation failed after maximum attempts" -ForegroundColor Red
499499
}
500500
else {
501-
Write-Host "[INFO] Operation cancelled no key provided" -ForegroundColor Yellow
501+
Write-Host "[INFO] Operation cancelled - no key provided" -ForegroundColor Yellow
502502
}
503503

504504
Write-Host ""

deploy/windows_setup.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ try {
169169
Write-Host ""
170170
Write-Host "API Token Configuration" -ForegroundColor Cyan
171171
Write-Host ""
172-
Write-Host "[INFO] Token storage priority: Windows Credential Manager File-based DPAPI" -ForegroundColor Yellow
172+
Write-Host "[INFO] Token storage priority: Windows Credential Manager -> File-based DPAPI" -ForegroundColor Yellow
173173
Write-Host ""
174174

175175
# Load DPAPI assembly (for fallback PowerShell storage)

0 commit comments

Comments
 (0)