/** * Persistent permission grants — the allow-list (`wonk-allow.toml`). * * The TypeScript sibling of the Rust engine's `permission_grants.rs`. The * {@link PermissionHook} gate closes on an `Ask` verdict by prompting a human. * Without persistence that prompt is *approve-once*: the same command re-asks on * every run. This module ports smooth's `wonk-allow.toml` allow-list so a * human's "approve always" answer is remembered — a stored grant that matches a * later `Ask` auto-approves it **without prompting**. * * The on-disk schema is compatible with the Rust engine's `permission_grants` * (same TOML section names) so the files interoperate: * * ```toml * schema_version = 1 * * [network] * allow_hosts = ["api.openai.com", "*.openai.com"] * * [tools] * allow = ["web_search", "vendor.file_write"] * * [bash] * allow_patterns = ["cargo ", "pnpm "] * ``` * * - `network.allow_hosts` — exact host or `*.suffix` glob (case-insensitive). * - `tools.allow` — exact tool name (writes / unknown tools grant by name). * - `bash.allow_patterns` — a command *prefix*; the trailing space in `"cargo "` * is significant (stops it matching `cargonaut`). * * There is no deny section: a stored grant can only upgrade an `Ask`, **never** * waive a `Deny` circuit-breaker (see {@link PermissionHook}). * * ponytail: in-memory + TOML round-trip only — no filesystem I/O helpers * (atomic writes / layered load / home-dir resolution). This crate is consumed * as a library; the CLI/daemon owns persistence and passes the parsed grants in. * Add fs helpers here only if a library consumer actually needs them. */ /** * The kind of resource a grant covers — one of the three grantable `Ask` shapes. * (`Deny` circuit-breakers are never grantable.) A discriminated union. */ export type GrantQuery = { kind: 'network'; host: string; } | { kind: 'tool'; tool: string; } | { kind: 'bash'; prefix: string; }; /** * In-memory allow-list. Case-insensitive matching for hosts and bash prefixes; * exact match for tool names. */ export declare class PermissionGrants { /** Always 1. Reserved for forward-compatible migrations. */ schemaVersion: number; readonly allowHosts: Set; readonly allowTools: Set; readonly allowBashPatterns: Set; /** True if `host` is covered by the network allow-list. */ matchesHost(host: string): boolean; /** True if `toolName` is in the tools allow-list (exact match). */ matchesTool(toolName: string): boolean; /** True if `command` starts with any bash allow prefix (case-insensitive). */ matchesBash(command: string): boolean; /** True if `query`'s exact entry is already stored. */ contains(query: GrantQuery): boolean; /** Add a grant. Idempotent. */ add(query: GrantQuery): void; /** Union `other` into `this`. */ mergeWith(other: PermissionGrants): void; /** Parse from a TOML string. Missing sections default to empty. */ static parse(tomlText: string): PermissionGrants; /** Serialize to TOML. Empty sections are omitted. Entries are sorted for a stable round-trip. */ toTomlString(): string; } /** * Glob match for a single host pattern (case-insensitive): * - exact host: `api.example.com` matches only that. * - `*.example.com` / `.example.com`: any subdomain **and** the bare apex. * - a bare suffix (`example.com`) matches only itself (no substring match, so * `evil-example.com` never slips past `example.com`). */ export declare function hostMatchesGlob(host: string, pattern: string): boolean; //# sourceMappingURL=permissionGrants.d.ts.map