import Anthropic from '@anthropic-ai/sdk'; import type { Finding } from '@manehorizons/cadence-types'; import { type SpawnFn } from './host-cli-client.js'; /** * Phase 25.2 — security-audit verifier. The final, most expensive gate: * fires at `cadence settle run` after code-review and before SUMMARY write * when `'security-audit'` is in the effective gate set (strict×complex * only — the rarest cell). CRITICAL findings refuse settle unless * `--force` / `--allow-security-audit-failure`. All findings (any * severity) land on `SUMMARY.securityAudit`. */ export interface SecurityAuditInput { /** Touched files (union across draft tasks). Scopes the diff + prompt. */ files: string[]; /** Unified diff (`git diff HEAD -- `). May be empty. */ diff: string; } export interface SecurityAuditResult { /** Flat finding list (not per-file — security issues span files). */ findings: Finding[]; provider: string; model?: string; } export interface SecurityAuditVerifier { readonly name: string; /** * Phase 184: `opts` mirrors `Verifier.verify`'s shape * (`packages/core/src/verify/verifier.ts`) — an optional external * `AbortSignal` plus a `traceId` for logging. Every implementation must * accept it and keep behaving identically when it is omitted. */ verify(input: SecurityAuditInput, opts?: { signal?: AbortSignal; traceId?: string; }): Promise; } /** * Deterministic mock — walks the unified diff and flags every added line * carrying a hardcoded `Authorization:` header value or a JWT-shaped string * as CRITICAL. Empty diff (or no matches) returns no findings. The rule is * intentionally narrow: real OWASP review lives in the Anthropic provider. */ export declare class MockSecurityAuditVerifier implements SecurityAuditVerifier { readonly name = "mock"; verify(input: SecurityAuditInput, _opts?: { signal?: AbortSignal; traceId?: string; }): Promise; } export interface AnthropicSecurityAuditVerifierOptions { apiKey?: string; model?: string; maxTokens?: number; /** Inject a client for tests; production callers should omit this. */ client?: Anthropic; } export declare class AnthropicSecurityAuditVerifier implements SecurityAuditVerifier { readonly name = "anthropic"; private readonly client; private readonly model; private readonly maxTokens; constructor(opts?: AnthropicSecurityAuditVerifierOptions); verify(input: SecurityAuditInput, opts?: { signal?: AbortSignal; traceId?: string; }): Promise; } export interface LocalSecurityAuditVerifierOptions { baseURL: string; model: string; transport?: typeof fetch; } export declare class LocalSecurityAuditVerifier implements SecurityAuditVerifier { private readonly o; readonly name = "local"; constructor(o: LocalSecurityAuditVerifierOptions); verify(input: SecurityAuditInput, opts?: { signal?: AbortSignal; traceId?: string; }): Promise; } export interface HostCliSecurityAuditVerifierOptions { /** Host CLI binary name or path, e.g. `"claude"` or `"codex"`. */ bin: string; model?: string; /** Inject a spawn implementation for tests; production callers should omit this. */ spawnImpl?: SpawnFn; } /** * Phase 191 — spawns the user's already-installed, already-authenticated * host CLI (`claude`/`codex`) in headless mode via `hostCliJSON` instead of * calling an HTTP endpoint. Structurally mirrors `LocalSecurityAuditVerifier` * — same early-return, `{signal, traceId}` opts threading, * `SYSTEM_PROMPT`/`formatUserMessage`/`SecurityAuditResponseSchema`, only the * transport differs. */ export declare class HostCliSecurityAuditVerifier implements SecurityAuditVerifier { private readonly o; readonly name = "host-cli"; constructor(o: HostCliSecurityAuditVerifierOptions); verify(input: SecurityAuditInput, opts?: { signal?: AbortSignal; traceId?: string; }): Promise; } //# sourceMappingURL=security-audit.d.ts.map