import { type SecretBuffer } from '../crypto/index.js'; export interface PortalInfo { handle: string; kind: 'evm'; /** EVM address (secp256k1) — 0x-prefixed, lowercase. */ address: string; /** Solana address (ed25519) derived from the same secret — base58. */ svmAddress: string; } export declare class HandleLoadError extends Error { readonly cause?: unknown; constructor(message: string, cause?: unknown); } /** * In-memory registry of handle → unlocked SecretBuffer. * * Lifecycle inside sigil-mcp: * - Constructed empty + locked at startup. * - `sigil unlock` calls loadFromDir / addEntry → table becomes unlocked. * - `sigil lock` calls lock() → entries zeroed + cleared, table re-lockable. * - Process exit calls dispose() → final teardown, no further use. * * The unlocked flag is tracked separately from entry count so that an unlock * with zero portals on disk still distinguishes "no portals exist" (handle * lookup → PORTAL_NOT_FOUND) from "never unlocked" (handle lookup → * DAEMON_LOCKED). */ export declare class HandleTable { #private; static parseHandle(handle: string): { kind: 'evm'; name: string; }; static handleFromFilename(filename: string): string | null; /** * Load every keyfile in `dir` named `.sigil`, decrypting each with * the same passphrase. Throws HandleLoadError on any failure; on failure * the table is left locked with any partially-loaded entries zeroized. * * Order: deterministic by sorted filename, so audit logs and list_portals * output are stable across restarts. * * Marks the table as unlocked on success — even if the directory was * empty (zero portals to load). After that, sign calls see PORTAL_NOT_FOUND * instead of DAEMON_LOCKED. */ loadFromDir(dir: string, passphrase: Buffer): void; /** * Add a handle directly (for tests or for non-file-backed key sources). * Takes ownership of the SecretBuffer; lock()/dispose() will zeroize it. * Does NOT flip the unlocked flag — loadFromDir does that once after a * successful pass. Tests that want an unlocked table should call * markUnlocked() explicitly. */ addEntry(handle: string, secret: SecretBuffer): void; /** * Explicitly mark the table as unlocked without loading anything. Useful * for tests that pre-populate via addEntry and want sign methods to * succeed. */ markUnlocked(): void; has(handle: string): boolean; /** * Returns the SecretBuffer for the handle. Caller must NOT dispose it — * the table owns the lifetime. */ get(handle: string): SecretBuffer | undefined; list(): PortalInfo[]; isUnlocked(): boolean; /** * Zeroize every entry and re-lock the table. The table remains usable — * a subsequent unlock can repopulate it. Idempotent. */ lock(): void; /** * Final teardown: zeroize every key and mark the table unusable. After * dispose(), get/has/list/lock/markUnlocked/addEntry/loadFromDir throw. * Idempotent. */ dispose(): void; get isDisposed(): boolean; } //# sourceMappingURL=handles.d.ts.map