export interface BotGuardConfig { apiKey?: string; organizationId?: string; apiUrl?: string; shieldId?: string; shieldKey?: string; /** Windows DPAPI-protected shield key. Preferred over plaintext shieldKey. */ shieldKeyDpapi?: string; scan?: { endpoint?: string; description?: string; systemPrompt?: string; categories?: string[]; attackCount?: number; failThreshold?: number; format?: 'json' | 'table' | 'summary'; mode?: 'sync' | 'async'; webhookFormat?: string; }; } /** * Outcome of the most recent DPAPI PowerShell attempt in THIS process — * the fleet's "is PowerShell blocked on this machine?" health bit, derived * from work we had to do anyway (never a dedicated PowerShell spawn). * spawnOk=false means powershell.exe/pwsh.exe could not even start (EDR/ * AppLocker block, missing shells); spawnOk=true + decryptOk=false means the * shell ran but the blob would not decrypt (wrong user profile / corrupt). */ export interface PowershellHealth { spawnOk: boolean; decryptOk: boolean; checkedAt: string; /** FullLanguage / ConstrainedLanguage / RestrictedLanguage — captured only when a decrypt fails (extra spawn is failure-path-only). */ languageMode?: string; } export declare function getPowershellHealth(): PowershellHealth | undefined; /** * PowerShell language mode — the "is this a hardened WDAC/AppLocker fleet * machine?" bit that explained the lptx1110 incident. Spawned only on the * DPAPI failure path (and from the deep self-test), never on healthy runs. */ export declare function capturePowershellLanguageMode(): string | undefined; /** * PSCredential.GetNetworkCredential() instead of Marshal::SecureStringToBSTR: * hardened fleets run PowerShell in Constrained Language Mode, where the * [Runtime.InteropServices.Marshal] calls are forbidden (script fails -> * exit 1 -> "Shield key not available" -> every hook 401s fail-closed). The * PSCredential technique is on CLM's approved-type list and decrypts the same * DPAPI-protected SecureString in every language mode. Exported so the CLM * regression test runs this EXACT text inside a ConstrainedLanguage session. */ export declare const DPAPI_DECRYPT_SNIPPET = "$secure=ConvertTo-SecureString -String $env:FCD_DPAPI_VALUE; (New-Object System.Management.Automation.PSCredential('fcd', $secure)).GetNetworkCredential().Password"; /** * Deep self-test probe: encrypt AND decrypt a throwaway value with the exact * DPAPI snippets used for the shield key. Encryption alone can succeed on a * machine that can never decrypt (the pre-v1.21.32 bricking bug) — only the * full roundtrip proves the credential store works. */ export declare function dpapiRoundtripProbe(): { ok: boolean; detail: string; }; export declare function getHomeConfigPath(): string; export declare function loadConfig(configPath?: string): BotGuardConfig; export declare function getDefaultConfigPath(): string; export declare function saveShieldConfig(input: { shieldId: string; shieldKey?: string; apiUrl?: string; }): string; export interface SetupConfigInput { apiKey?: string; organizationId?: string; apiUrl?: string; shieldId?: string; shieldKey?: string; } export interface ResolvedCliCredentials { apiKey?: string; organizationId?: string; apiUrl: string; shieldId?: string; shieldKey?: string; } /** * Daemon→child credential handoff: the daemon injects its already-decrypted * in-memory creds as FCD_SHIELD_ID + FCD_SHIELD_KEY when spawning sweep * children (see discoverSweepCredentialEnv in daemon.ts). When BOTH are * present the child must use them as-is and skip the DPAPI decrypt — that * decrypt spawns powershell.exe, which EDR on hardened fleet machines can * block (and flags as suspicious even when it merely fails). Requiring the * pair keeps a stray single env var (e.g. AGENTGUARD_SHIELD_KEY from a * Cursor-plugin setup) from overriding the machine's enrolled key. * Pure — unit-tested. */ export declare function daemonHandoffShieldKey(env?: NodeJS.ProcessEnv): string | undefined; /** * Which source supplied the shield key on the most recent resolution — the * codes-only trace shipped in the collect_diagnostics bundle (never the key * itself). `none_dpapi_broken` is the credential-broken state: a DPAPI blob * exists but would not decrypt and no fallback source was available. */ export type ShieldKeySource = 'override' | 'daemon_handoff' | 'native_store' | 'machine_file' | 'dpapi' | 'plaintext_config' | 'env' | 'none' | 'none_dpapi_broken'; export interface CredentialResolutionTrace { shieldKeySource: ShieldKeySource; dpapiAttempted: boolean; at: string; } export declare function getCredentialResolutionTrace(): CredentialResolutionTrace | undefined; /** Merge saved ~/.fullcourtdefense.yml + env + optional CLI flag overrides. */ export declare function resolveCliCredentials(config: BotGuardConfig, overrides?: Partial, options?: { skipDpapi?: boolean; }): ResolvedCliCredentials; /** * Credential resolution that is guaranteed to spawn NO child process — for * frequent low-privilege callers (watchdog beacon every 5 min). Skips the * DPAPI/PowerShell decrypt entirely; on a DPAPI-enrolled machine this may * yield no shieldKey, in which case the caller sends a constrained * (unauthenticated) beacon instead. */ export declare function resolveCliCredentialsShellFree(config: BotGuardConfig, overrides?: Partial): ResolvedCliCredentials; export declare function isCliSetupComplete(config: BotGuardConfig): boolean; /** Fail fast with a clear message when setup was not run. */ export declare function requireCliSetup(config: BotGuardConfig, overrides?: Partial, options?: { requireApiKey?: boolean; requireOrganizationId?: boolean; requireShield?: boolean; }): ResolvedCliCredentials; export declare function saveSetupConfig(input: SetupConfigInput, targetPath?: string): string; export declare function resolveSystemPrompt(value: string): string;