Private/Helpers.ps1

# Default environment variable mapping for known services.
# Format: service-name → ENV_VAR_NAME
# Used by Import-PCSecrets when no explicit envVar is stored in the secret entry.
$script:DefaultEnvVarMap = @{
    'openai'       = 'OPENAI_API_KEY'
    'anthropic'    = 'ANTHROPIC_API_KEY'
    'gemini'       = 'GEMINI_API_KEY'
    'azure'        = 'AZURE_SPEECH_KEY'
    'redmine'      = 'REDMINE_API_KEY'
    'google-cse'   = 'GOOGLE_CSE_API_KEY'
    'brave-search' = 'BRAVE_SEARCH_API_KEY'
    'firecrawl'    = 'FIRECRAWL_API_KEY'
}

function Get-PCSecretsPath {
    <#
    .SYNOPSIS
        Returns the resolved path to the secrets store directory and file.
    #>

    [CmdletBinding()]
    [OutputType([hashtable])]
    param()

    $home = if ($env:POWERCRAFT_HOME) {
        $env:POWERCRAFT_HOME
    }
    else {
        Join-Path ([Environment]::GetFolderPath('UserProfile')) '.powercraft'
    }

    return @{
        Home = $home
        File = Join-Path $home 'secrets.json'
    }
}

function Read-PCSecretsFile {
    <#
    .SYNOPSIS
        Reads and parses the secrets JSON file. Returns empty hashtable if missing/invalid.
    #>

    [CmdletBinding()]
    [OutputType([hashtable])]
    param()

    $paths = Get-PCSecretsPath
    if (-not (Test-Path $paths.File)) {
        return @{}
    }

    try {
        $content = Get-Content $paths.File -Raw -ErrorAction Stop
        if ([string]::IsNullOrWhiteSpace($content)) { return @{} }
        return ($content | ConvertFrom-Json -AsHashtable -ErrorAction Stop)
    }
    catch {
        Write-Warning "PowerCraft.Secrets: Failed to read secrets file: $_"
        return @{}
    }
}

function Write-PCSecretsFile {
    <#
    .SYNOPSIS
        Writes the secrets hashtable to the JSON file with restrictive permissions.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$Secrets
    )

    $paths = Get-PCSecretsPath

    # Ensure directory exists
    if (-not (Test-Path $paths.Home)) {
        New-Item -ItemType Directory -Path $paths.Home -Force | Out-Null
    }

    # Write JSON
    $Secrets | ConvertTo-Json -Depth 10 | Set-Content $paths.File -Encoding UTF8

    # Set restrictive permissions
    Set-PCFilePermissions -Path $paths.File
}

function Set-PCFilePermissions {
    <#
    .SYNOPSIS
        Sets owner-only read/write permissions on a file.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Path
    )

    try {
        if ($IsWindows) {
            $user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
            & icacls $Path /inheritance:r /grant "${user}:F" 2>&1 | Out-Null
        }
        else {
            & chmod 600 $Path 2>&1 | Out-Null
        }
    }
    catch {
        Write-Verbose "PowerCraft.Secrets: Could not set restrictive permissions: $($_.Exception.Message)"
    }
}

function Resolve-PCEnvVarName {
    <#
    .SYNOPSIS
        Resolves the environment variable name for a given service.
        Checks: explicit envVar in secret entry → default map → generated name.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Name,

        [Parameter()]
        [hashtable]$SecretEntry
    )

    # 1. Explicit envVar in the entry
    if ($SecretEntry -and $SecretEntry['envVar']) {
        return $SecretEntry['envVar']
    }

    # 2. Default mapping
    if ($script:DefaultEnvVarMap.ContainsKey($Name)) {
        return $script:DefaultEnvVarMap[$Name]
    }

    # 3. Generate: service-name → SERVICE_NAME_API_KEY
    return ($Name.ToUpper() -replace '-', '_') + '_API_KEY'
}