type JudgeEndpointConfig = { policy?: "default"; endpoint?: string; } | { policy: "self-hosted"; endpoint: string; verifyPubKey: string; }; interface ValidatedEndpoint { url: string; policy: "default" | "self-hosted"; verifyPubKey: string | null; } /** * Builds the trusted judge host set. * * The compiled-in default is always trusted: a `prod` build resolves it to * atbash.ai, a dev build to whatever DEV_ENDPOINT was set at build time. No * dev host is spelled out in source, and dev builds still validate their own * default. * * Exported for tests only. The set is a build-time value and is deliberately * never read from the process environment — an env var would let anyone widen * the allowlist of an already-shipped artifact, which is the silent-redirection * attack the allowlist exists to prevent (F-003). Asserting that requires * calling this with the environment set, so it cannot stay module-private. * * @internal */ declare function buildAllowedJudgeHosts(): ReadonlySet; declare function validateJudgeEndpoint(judge?: JudgeEndpointConfig): ValidatedEndpoint; /** * User-facing types. Two groups: * - Core types — the exact shapes the Rust core emits across the NAPI * boundary (field names match the serde output byte-for-byte). * - SDK types — the HTTP-facing result shapes the `Atbash` client returns, * already normalized (verdict casing, status). */ /** `generate_keypair` result. Note the `priv_key` / `pub_key` field names. */ interface KeyPair { priv_key: string; pub_key: string; } /** `load_agent` result. Note the `privkey` / `pubkey` field names. */ interface AgentAuth { privkey: string; pubkey: string; } interface SecretMatch { kind: string; length: number; } interface RedactResult { redacted: string; found: SecretMatch[]; } interface MemoryEntry { key: string; value: string; source?: string; timestamp?: number; } interface MemorySnapshot { entries: MemoryEntry[]; takenAt: number; } interface ModifiedEntry { key: string; before: string; after: string; } type AnomalyType = "behavioral_override" | "bulk_insertion" | "safety_bypass" | "privilege_escalation" | "gradual_drift"; type AnomalySeverity = "low" | "medium" | "high" | "critical"; interface MemoryAnomaly { type: AnomalyType; severity: AnomalySeverity; description: string; entries: string[]; } interface MemoryDiffResult { safe: boolean; added: MemoryEntry[]; removed: MemoryEntry[]; modified: ModifiedEntry[]; anomalies: MemoryAnomaly[]; } /** AES-256-GCM output from `encryptMemoryContent`. */ interface EncryptedMemory { ciphertext: Buffer; nonce: Buffer; } /** Memory scanner verdict — matches the judge-response colour taxonomy. */ type MemoryScanVerdict = "green" | "yellow" | "red"; /** Result of `scanMemory` (regex pre-filter and/or LLM judge). */ interface MemoryScanResult { safe: boolean; verdict: MemoryScanVerdict; reason: string; confidence: number; /** Severity 1 (poisonous) → 10 (benign). LLM sets it; falls back to red=2/yellow=5/green=8 when the LLM omits the SCORE prefix or the regex pre-filter short-circuits. */ score: number; toolCallId?: string; } /** Options for `scanMemory`. Passed through to `judgeAction`. */ interface MemoryScanOptions { /** Threshold for LLM confidence to escalate a green verdict to yellow. Default: 0.6 */ threshold?: number; /** Judge endpoint override. Same shape as ClientOpts.endpoint. */ endpoint?: string; /** Self-hosted judge response-signing pubkey. */ verifyPubKey?: string; /** Org name for chain resolution. */ orgName?: string; /** Tool name for on-chain audit log. */ toolName?: string; /** JSON-serialized tool args for on-chain audit log. */ toolArgsJson?: string; } /** * Which Atbash chain an action runs against. `public` is the shared * testnet (Free plan); `private` is reserved for Private / Swarm / * Enterprise tier subscribers. The SDK resolves which one to use from * the org's subscription via `orgName` — callers normally don't need * to pass this manually. */ type Network = "public" | "private"; /** * Per-call chain overrides. Pass exactly what you need to override — * `network` selects between the SDK's known chains, `blockchainRid` / * `nodeUrls` pin a fully custom chain. Pass none of these to fall back * to the SDK's defaults (or to org-resolved chain when `orgName` is set). */ interface ChainOpts { network?: Network; blockchainRid?: string; nodeUrls?: readonly string[]; } /** Canonical verdict after normalization. */ type Verdict = "ALLOW" | "HOLD" | "BLOCK" | "No verdict"; /** Canonical judgment status after normalization. */ type JudgmentState = "pending" | "answered" | "error"; /** * Provider attribution on a judged action. The trailing `string & {}` * accepts custom provider names without losing autocompletion on the * canonical ones. */ type Provider = "openai" | "google" | "microsoft" | "custom" | (string & {}); /** Verdict action_type carried in the judge response. */ type ActionType = "allow" | "hold_for_user_confirm" | "block" | (string & {}); /** Pubkey value as accepted on the wire — hex string, Buffer, or GTV bytes. */ type PubkeyValue = string | Buffer | { data: number[]; }; interface LogToolCallResult { success: boolean; toolCallId: string | null; signedHex?: string; error?: string; } interface JudgeResult { verdict: Verdict; actionType: string; reason: string; confidence: number; provider: string; latencyMs: number; toolCallId: string; onChain: boolean; /** Severity 1 (poisonous) → 10 (benign). Present on memory-scan responses; absent for regular tool-call judgments. */ score?: number; /** * Whether the org's protection mode actually acts on a HOLD/BLOCK verdict. * `false` in Monitor mode (verdict is logged for observation, agent is NOT * jailed and the action is not held); `true` in Enforce mode. */ enforced: boolean; /** Server-reported protection mode: `off`, `monitor`, or `enforce`. */ enforcementMode: string; /** * Server-reported response status. The judge sets `"logged"` on the AUDIT * tier, where it deliberately returns no verdict. This is the ONLY signal * that distinguishes "the server chose not to enforce" from "the verdict is * missing" — never infer the former from a null verdict alone. */ status: string; } interface JudgmentStatus { status: JudgmentState; verdict: Verdict; reason: string; judgmentId: string; onChain?: boolean; cached?: boolean; responseTimeMs?: number; } interface TierInfo { orgName: string; tier: string; verdictEnabled: boolean; enforcementEnabled: boolean; } /** * Plan-level subscription metadata. Returned by `org-subscription` — * field names match the on-chain shape (snake_case) so the response * can be inspected without renaming. */ interface Subscription { subscription_name: string; agent_number: number; is_private_blockchain: boolean; monthly_price: number; yearly_price: number; } /** * Org's binding to a subscription on a specific chain. The chain is * implied by which BRID the query hit (controlled by the `network` * query param when fetching). */ interface OrgSubscription extends Subscription { org_name: string; duration_months: number; assigned_at: number; expires_at: number; is_active: boolean; } interface ToolCallRecord { toolCallId: string; agentPubkey: string; toolName: string; commandText: string; toolArgsJson: string; contextText: string; orgName: string; rowid: number; } interface ToolCallFull { toolCallId: string; agentPubkey: string; toolName: string; commandText: string; contextText: string; orgName: string; toolArgsJson?: string; createdAt?: number; actionType?: string; resultStatus?: string; verdictColor?: string; verdictReason?: string; verdictSource?: string; verdictResponseTimeMs?: number; } interface HeldAction { judgmentId: string; agentPubkey: string; actionText: string; actionContext: string; verdict: Verdict; reason: string; createdAt: number; } interface HeldActionReview { judgmentId: string; actionText: string; status: string; reviewNote: string; reviewedAt: number; createdAt: number; reviewedBy?: string; } interface AgentPolicy { policy: string; isJailed: boolean; isCustom: boolean; defaultPolicy: string; } /** Optional structured logger. */ interface AtbashLogger { info?(...args: unknown[]): void; warn?(...args: unknown[]): void; } /** Options accepted by the `Atbash` constructor. */ interface AtbashOptions { endpoint?: string; timeoutMs?: number; nodeUrls?: readonly string[]; blockchainRid?: string; /** * Default org name. When set, `judgeAction` / `auditToolCall` resolve * the chain via the `org_networks` map on every call (with the * per-client cache short-circuiting the second hit onwards). Per-call * overrides on the method options still win. */ orgName?: string; /** * Default response-signing pubkey for `judgeAction` verification. Set * automatically by `Atbash.fromConfig` for self-hosted endpoints; a * per-call `verifyPubKey` still overrides it. */ verifyPubKey?: string; /** * Org's encryption public key (33-byte compressed secp256k1, hex). When set, * tool calls are sealed to it and signed as `log_encrypted_tool_call` instead * of `log_tool_call`, so the action never reaches the block in clear. * * Required for any org that has registered a key — the contract refuses * plaintext for those. Omitted, behaviour is unchanged. A per-call * `orgEncryptionPubKey` overrides this, same as `verifyPubKey`. */ orgEncryptionPubKey?: string; /** When true (default), `auditToolCall` denies on any error. */ failClosed?: boolean; logger?: AtbashLogger; } /** Canonical decision returned by `auditToolCall`. */ type DecisionVerdict = "ALLOW" | "HOLD" | "BLOCK" | "ERROR"; interface Decision { allow: boolean; verdict: DecisionVerdict; reason?: string; toolCallId?: string; } /** Input to `auditToolCall`. */ interface ToolCallInput { toolName: string; args?: unknown; context?: string; /** * Plain-language facts about the action, produced by the caller after * any tool-specific parsing (e.g., an ERC-20 contract address resolved * to `{asset: "USDT"}`). Not run through the secret redactor — the * caller is expected to keep secret-shaped values out. The judge LLM * sees this as a distinct PARSED_METADATA block, so it can apply * asset- or recipient-specific policy even when raw addresses in * `args` were redacted. */ resolved?: Record; } /** Options accepted by `Atbash.fromConfig`. All fields are explicit overrides. */ interface FromConfigOptions { /** Inline private key. Overrides env / config-file / key-file resolution. */ agentKey?: string; /** Path to the agent key file (default `~/.config/atbash/guard-client-key`). */ keyPath?: string; /** Judge endpoint config — validated against the allowlist / self-hosted policy. */ judge?: JudgeEndpointConfig; blockchainRid?: string; timeoutMs?: number; nodeUrls?: readonly string[]; /** Default org name — see {@link AtbashOptions.orgName}. */ orgName?: string; failClosed?: boolean; logger?: AtbashLogger; } /** Options accepted by `judgeAction`. */ interface JudgeOptions { toolName?: string; toolArgsJson?: string; provider?: string; model?: string; verifyPubKey?: string; /** Per-call override of {@link AtbashOptions.orgEncryptionPubKey}. */ orgEncryptionPubKey?: string; /** * Org name — when set, the SDK resolves which chain the agent lives * on via the off-chain `org_networks` map (authoritative) before * signing. Overrides any `chainOpts.blockchainRid` hint when the map * has an entry. */ orgName?: string; /** * Explicit per-call chain override. Use to pin a specific chain for * one call; otherwise the SDK uses the constructor defaults or the * org-resolved chain. */ chainOpts?: ChainOpts; /** * Plain-language facts about the action — see * {@link ToolCallInput.resolved}. Also accepted here for callers that * use `judgeAction` directly without going through `auditToolCall`. */ resolved?: Record; /** Alternate flow: "memory-scan" tells the dashboard to use `context` as trusted policy and skip AGT/OPA/chain writes. Set by `scanMemory`; usually not needed at the call site. */ mode?: "memory-scan"; } /** Options accepted by `logToolCall`. */ interface LogToolCallOptions { toolName?: string; toolArgsJson?: string; /** Per-call chain override — same semantics as `JudgeOptions.chainOpts`. */ chainOpts?: ChainOpts; /** Per-call override of {@link AtbashOptions.orgEncryptionPubKey}. */ orgEncryptionPubKey?: string; } interface ChainConfig { readonly network: Network; readonly blockchainRid: string; readonly nodeUrls: readonly string[]; } declare class Atbash { readonly auth: AgentAuth; readonly endpoint: string; readonly nodeUrls: readonly string[]; readonly blockchainRid: string; /** Default org name used by `auditToolCall` / `judgeAction`. */ readonly orgName?: string; /** Default judge response-signing pubkey, if configured (see fromConfig). */ readonly verifyPubKey?: string; /** Default org encryption key — see {@link AtbashOptions.orgEncryptionPubKey}. */ readonly orgEncryptionPubKey?: string; /** When true (default), `auditToolCall` denies on any error. */ readonly failClosed: boolean; /** Org key learned from the last agent-exists check, for this agent only. */ private _orgKeyFromChain; private readonly logger; private readonly http; /** * Per-client cache of resolved chains. Keyed by orgName so repeated * calls don't re-hit the dashboard. Cleared by `clearChainCache()`. */ private readonly _chainCache; /** * Cached bearer token for risk-engine / insurance read calls. Built * lazily as a signed `log_tool_call` tx and refreshed every 4 min so * server-side replay protection windows never expire it mid-session. */ private _authBearer; constructor(privkey: string, options?: AtbashOptions); /** * Construct from resolved config: explicit overrides → env vars → the * `~/.config/atbash/config.json` file (see userConfig.resolve). The private * key comes from `agentKey` (override/env/file) or, failing that, the agent * key file (`~/.config/atbash/guard-client-key`). The judge endpoint is * validated against the trusted allowlist / self-hosted policy; a * self-hosted endpoint's `verifyPubKey` becomes the client default. */ static fromConfig(options?: FromConfigOptions): Atbash; get pubkey(): string; get privkey(): string; /** * `GET /api/ai/exists?pubkey=…[&network=…]` — defaults to this client's * pubkey. Pass `opts.network` when the caller already knows which * network the agent lives on (e.g. after resolving via `orgName`) so * the dashboard queries that chain directly instead of falling back * across public → private, which double-round-trips and can return * false negatives when the fallback chain client is misconfigured. */ checkAgentExists(pubkey?: string, opts?: { network?: Network; }): Promise; /** * Pre-flight `checkAgentExists`, then sign `log_tool_call` locally and * return the signed tx hex. The server broadcasts to chain. */ logToolCall(action: string, context?: string, options?: LogToolCallOptions): Promise; /** * Sign log_tool_call + optionally judge_action, POST /api/v1/judge. * * `verifyPubKey` checks the `X-Atbash-Signature` header against the exact * response bytes via the Rust core's `verifySignature`. */ judgeAction(action: string, context?: string, options?: JudgeOptions): Promise; private _judgeAction; /** * High-level guard: redact secrets, submit for judgement, and collapse the * result into an allow/deny `Decision`. Fails closed by default — any error * (judge unreachable, unrecognized verdict) denies unless `failClosed` is * explicitly false. */ auditToolCall(input: ToolCallInput): Promise; private fail; getJudgmentStatus(judgmentId: string, agentPubkey?: string): Promise; getToolCalls(maxCount: number): Promise; getOrgToolCalls(orgName: string, maxCount: number): Promise; getAgentToolCalls(agentPubkey: string, maxCount: number): Promise; getToolCallCount(): Promise; getToolCallFull(toolCallId: string): Promise; getOrgTierInfo(orgName: string): Promise; getPendingHeldActions(orgName: string, maxCount: number): Promise; getHeldActionReviews(orgName: string, maxCount: number): Promise; getAgentDetail(agentPubkey: string): Promise>; getAgentPolicy(agentPubkey: string): Promise; getSafetyStats(): Promise>; /** * Org's subscription on a specific chain. The `network` arg selects * which chain to query; without it, the dashboard picks the default. * Returns null when the org has no record on that chain. */ getOrgSubscription(orgName: string, network?: Network): Promise; /** * Read the org's active network from the dashboard's off-chain * `org_networks` map. The map is the authoritative source after a * plan switch — subscription rows on the source chain go stale, but * the map is updated on every assign. Returns null when there's no * entry (caller falls back to per-chain subscription resolution). */ getActiveNetworkForOrg(orgName: string): Promise; /** * Resolve which chain an org's actions should run against. Cached * per-client by orgName. Resolution order: * 1. `org_networks` map (authoritative). * 2. Per-chain subscription fallback — public + private records * are fetched in parallel, with `is_private_blockchain` and * `assigned_at` reconciling mixed states. * Defaults to the public chain when nothing else resolves. */ resolveChainForOrg(orgName: string): Promise; /** * Resolve a chain given an already-fetched `org_networks` map result. * Split out from {@link resolveChainForOrg} so callers that have already * queried the map (the judge path) don't fetch /api/org-network twice. * Caches per orgName like its caller. */ private resolveChainFromMap; /** Drop any cached chain resolutions. Useful in tests. */ clearChainCache(): void; /** * Wrap an SDK method body in telemetry — records the call at start * and a success/error duration at end. Re-throws on failure so the * caller sees the original exception. Pass `agentPubkey` when the * method is keyed to a specific agent; tracked methods that don't * depend on an agent (read queries) pass `undefined`. */ private track; /** * Pick the BRID for a given per-call chain override. `blockchainRid` * takes precedence; otherwise `network` maps to one of the known * chains; otherwise the client's default. */ private bridFromChainOpts; /** * Get-or-create a Bearer token for dashboard reads. The token is a * signed `log_tool_call` op (locally signed, never submitted) — the * dashboard verifies the signature against the agent's pubkey. Cached * for 4 minutes; refreshed after that so a long-lived client never * trips the server's replay window. */ private getAuthBearer; private authHeaders; private riskEngineGet; private riskEnginePost; private riskEngineRecords; private raiseIfError; /** Wrap a failed HTTP *response* (non-2xx / non-200) as an AtbashAPIError. */ private httpError; /** Wrap a *transport* failure (fetch threw, no response) as an AtbashAPIError. */ private transportError; private json; static generateKeypair(): KeyPair; static isValidPrivateKey(hex: string): boolean; static derivePublicKey(privkey: string): string; static redactSecrets(text: string): RedactResult; static normalizeForMatching(text: string): string; static containsEvasionCharacters(text: string): boolean; } declare const DEFAULT_ENDPOINT: string; declare const DEFAULT_CHROMIA_NODE_URLS: readonly string[]; declare const DEFAULT_BLOCKCHAIN_RID: string; declare class AtbashAPIError extends Error { /** HTTP status code (or 0 if the request never completed). */ readonly status: number; /** Raw response body text (may be empty). */ readonly body: string; constructor(status: number, body: string, statusText?: string, endpoint?: string); } declare class SignatureVerificationError extends Error { constructor(message: string); } /** Normalize wire shapes (verdict casing, status, pubkey) to canonical forms. */ declare function normalizeVerdict(raw: unknown): Verdict; declare function normalizeStatus(raw: unknown): JudgmentState; /** Wire pubkey may be a hex string, a Buffer/Uint8Array, or `{ data: [...] }`. */ declare function pubkeyToHex(val: unknown): string; interface AtbashUserConfig { agentKey?: string; orgName?: string; judgeEndpoint?: string; blockchainRid?: string; provider?: string; providerModel?: string; } declare function getConfigDir(): string; declare function getConfigPath(): string; declare function loadUserConfig(): AtbashUserConfig; declare function saveUserConfig(config: AtbashUserConfig): void; declare function resolve(key: keyof AtbashUserConfig, flagValue?: string): string; declare function resolveKeyPath(input?: string): string; declare function loadAgentFromFile(keyPath?: string): AgentAuth; /** * Canonical secret kinds reported by the Rust core in `SecretMatch.kind`. * Wire is permissive (modelled as a free string in {@link SecretMatch}) * so unknown kinds don't break callers; use this union when narrowing. */ type SecretKind = "anthropic" | "openai" | "openai_project" | "github" | "google" | "google_oauth" | "aws_access_key" | "aws_secret_key" | "stripe" | "slack" | "slack_webhook" | "sendgrid" | "twilio_sid" | "mailgun" | "npm_token" | "jwt" | "private_key_pem" | "context_secret" | "bearer" | "base64" | "generic_token"; /** * Walk a JSON-shaped value and redact secrets inside every string leaf. * Object keys are not touched; only values. Arrays and nested objects * are recursed structurally so the returned value has the same shape. */ declare function redactJsonStrings(value: T): T; declare function verifyJudgeResponseSignature(bodyBytes: Uint8Array, signatureHex: string | null, pubKeyHex: string): { ok: boolean; reason?: string; }; /** Derive the 32-byte AES key from an agent's secp256k1 privkey (hex). Deterministic — same privkey always yields the same key. */ declare function deriveMemoryKey(privkey: string): Promise; /** Encrypt UTF-8 plaintext. `ciphertext` has the 16-byte GCM auth tag appended, matching the SDK's on-chain byte layout. */ declare function encryptMemoryContent(plaintext: string, key: Buffer): Promise<{ ciphertext: Buffer; nonce: Buffer; }>; /** Decrypt ciphertext produced by `encryptMemoryContent`. Throws on GCM tag mismatch — indicates tampered ciphertext or wrong key. */ declare function decryptMemoryContent(ciphertext: Buffer, nonce: Buffer, key: Buffer): Promise; /** * Scan a single memory entry for poisoning. * * `auth` is the agent that signs the on-chain audit log for the * LLM-judge call. Unicode-evasion presence is surfaced to the prompt * so the LLM can weight suspicion accordingly. */ declare function scanMemory(entry: MemoryEntry, auth: AgentAuth, opts?: MemoryScanOptions): Promise; /** * Scan multiple entries. Stops on the first red verdict by default — * set `stopOnRed: false` to scan every entry regardless. */ declare function scanMemoryBatch(entries: MemoryEntry[], auth: AgentAuth, opts?: MemoryScanOptions & { stopOnRed?: boolean; }): Promise; interface CommitMemoryOptions { /** Score in [1, 10]. Defaults to 5 (matches the Rell entity default). */ score?: number; /** Org name — when set, the SDK resolves which chain the agent lives on. */ orgName?: string; /** Atbash service endpoint for org→chain lookup. */ endpoint?: string; chainOpts?: ChainOpts; } interface RollbackMemoryOptions { orgName?: string; endpoint?: string; chainOpts?: ChainOpts; } /** * Encrypt `plaintext` and commit it as a new memory version via * `add_agent_memory`. The previous active version (if any) is * deactivated on-chain. * * The caller is responsible for running `scanMemory` first when * appropriate — this function does not gate on the verdict. */ declare function commitMemoryVersion(plaintext: string, auth: AgentAuth, opts?: CommitMemoryOptions): Promise; /** * Decrypted memory entry returned by the read helpers. * * `content` is the plaintext recovered from on-chain ciphertext. If * decryption fails (corrupted row, wrong key, etc.), `content` is * empty and `decryptError` carries the reason — the SDK returns the * row instead of throwing so one bad entry doesn't hide the rest. */ interface AgentMemoryEntry { id: number; content: string; decryptError?: string; score: number; isActive: boolean; createdAt: number; updatedAt: number; } /** Rollback event from `memory_rollback_log`. */ interface MemoryRollbackEvent { fromId: number; toId: number; reason: string; signer: string; createdAt: number; } /** * Cheap version-pointer probe. Returns just the id of the current * active memory (or null if none). No ciphertext is transferred — the * response is a single integer, so this is safe to call on every * memory-read hot path. */ declare function getActiveMemoryId(auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * Recent active memory entries — subset of active versions filtered * by the chain's `MEMORY_RECENT_WINDOW_MS`. For a time-unbounded view * of every currently active version, use `getAllAgentMemory`. */ declare function getActiveMemory(auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * All currently-active memory entries with no time cutoff. Use this * when you need every active version regardless of age. */ declare function getAllAgentMemory(auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * Full version history — active + inactive, most recent first. Used * by rollback UX to choose a target version. */ declare function getMemoryHistory(auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * Fetch a single memory entry by version id, including its current * `is_active` state. */ declare function getMemoryById(id: number, auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * Audit trail of rollback events for this agent, most recent first. */ declare function getRollbackHistory(auth: AgentAuth, chainOpts?: ChainOpts): Promise; /** * Roll back to a previously-committed memory version. The target * `toId` must exist and be currently inactive. `reason` is required * and is recorded on-chain in `memory_rollback_log`. */ declare function rollbackMemory(toId: number, reason: string, auth: AgentAuth, opts?: RollbackMemoryOptions): Promise; /** * Tool names that indicate a memory write. Lowercase — matched * case-insensitively so OpenClaw (lowercase) and Claude API family * (TitleCase) both hit. */ declare const DEFAULT_MEMORY_WRITE_TOOL_NAMES: ReadonlyArray; /** * File path substrings that indicate a memory-shaped target. Callers * extend or override via `classifyMemoryWrite` options. */ declare const DEFAULT_MEMORY_PATH_PATTERNS: ReadonlyArray; /** * Minimal shape of a `before_tool_call` context object across plugins. * The classifier reads only these fields — anything else is ignored. */ interface ClassifierToolContext { tool?: { name?: string; }; toolName?: string; name?: string; params?: unknown; args?: unknown; arguments?: unknown; } /** * Minimal shape of a `before_tool_call` event object across plugins. */ interface ClassifierToolEvent { toolName?: string; params?: unknown; args?: unknown; arguments?: unknown; } interface ClassifyMemoryWriteOptions { /** Override default memory-path patterns. */ patterns?: ReadonlyArray; /** Override default memory-write tool names. */ toolNames?: ReadonlyArray; } /** * If this tool call is writing to a memory-shaped path, return a * `MemoryEntry` suitable for `scanMemory` / `guardMemoryWrite`. * Otherwise return `null` — the SDK's memory path is skipped and the * caller can fall through to a regular tool-call audit. * * Empty-content writes return `null`: they can't carry a poisoning * payload, and the regular audit path still sees them. */ declare function classifyMemoryWrite(event: unknown, ctx: unknown, opts?: ClassifyMemoryWriteOptions): MemoryEntry | null; /** * Plugin-agnostic memory-write guard. * * A single call that replaces the plugin's usual memory-write branch: * classify → scan (Layer 1 regex + Layer 2 LLM) → gate on verdict → * persist to chain (fire-and-forget when allowed) → return decision. * * Plugins call this from their `before_tool_call` hook. When it returns * `{ handled: false }` the call wasn't a memory write and the plugin * should fall through to its regular tool-call audit. When * `{ handled: true }` the plugin returns `decision` directly. */ /** * Minimal logger accepted by `guardMemoryWrite`. Plugins pass their * host runtime's logger (openclaw's `api.logger`, MCP's console, etc.). * Only `info` and `warn` are used — omitted methods no-op. */ interface GuardLogger { info?: (message: string, meta?: unknown) => void; warn?: (message: string, meta?: unknown) => void; } interface GuardMemoryWriteInput extends ClassifyMemoryWriteOptions { /** The plugin's raw `before_tool_call` event. */ event: unknown; /** The plugin's `before_tool_call` context. */ ctx: unknown; /** Agent auth used to sign the scan's on-chain audit and the memory-commit tx. */ auth: AgentAuth; /** Judge endpoint override (dev vs prod). */ endpoint?: string; /** Self-hosted judge response-signing pubkey. */ verifyPubKey?: string; /** Org name for chain resolution (public vs org-private chain). */ orgName?: string; /** LLM confidence threshold for yellow escalation. Default 0.6. */ threshold?: number; /** When false, red verdicts log but don't block. Default true. */ enforce?: boolean; /** When true, emit a classifier-probe log line via `logger.info`. */ debug?: boolean; /** Optional logger for debug probe + persist-failure warnings. */ logger?: GuardLogger; } /** Plugin-facing decision. Shape mirrors what plugins return from `before_tool_call`. */ interface GuardMemoryDecision { allow: boolean; block?: boolean; reason?: string; } interface GuardMemoryWriteResult { /** True when this call was a memory write and `decision` was set. False = plugin should run its regular audit. */ handled: boolean; /** Present when handled. Plugin returns this from its hook. */ decision?: GuardMemoryDecision; /** Present when handled and scan ran. Absent when scan threw. */ scanResult?: MemoryScanResult; /** Present when handled. True when a chain-commit was dispatched (fire-and-forget). */ committed?: boolean; } /** * Guarded memory-write flow. Returns `{ handled: false }` when the tool * call isn't a memory write, otherwise returns a `decision` the plugin * should return from its hook. * * Verdict handling: * - `red` → not persisted to chain; decision blocks (unless `enforce: false`) * - `yellow` → persisted with LLM score; decision allows * - `green` → persisted with LLM score; decision allows * * Chain commit is fire-and-forget: network errors are logged via * `logger.warn` but never surfaced to the caller. This mirrors the * existing plugin behaviour — chain is for audit/recovery, not gating. */ declare function guardMemoryWrite(input: GuardMemoryWriteInput): Promise; /** * Aligns a local `MemoryPointer` with chain's active memory version * via a TTL-cached pointer check. Inside the TTL window: no-op. * Past it: one cheap chain query for the current active id; only on * mismatch does the full row get refetched and decrypted. * * Fail modes: * - Chain unreachable → throws the network error verbatim; caller * serves the local copy and retries on the next check. * - Tampered ciphertext (GCM tag mismatch) → throws * `MemoryIntegrityError`. Fail-closed — never silent. */ /** Per-agent state the caller persists between sync calls. */ interface MemoryPointer { /** Last known chain-active memory id, or null if the agent had no active memory at the last check. */ activeId: number | null; /** Wall-clock ms of the last successful chain check. Use 0 to force a check on the next call. */ checkedAt: number; } interface SyncMemoryOptions { /** Trust the pointer without touching chain for this many ms since `checkedAt`. Default 30_000. */ ttlMs?: number; /** Skip the TTL gate and force a chain check this call. Default false. */ force?: boolean; chainOpts?: ChainOpts; } /** * `drifted: false` — pointer is still valid; caller can keep serving the local copy. * `drifted: true` — active id changed on chain; `current` is the fresh decrypted row * (or `null` if active memory was removed entirely). */ type SyncMemoryResult = { drifted: false; pointer: MemoryPointer; } | { drifted: true; current: AgentMemoryEntry | null; pointer: MemoryPointer; }; /** Thrown when a fetched active row fails its GCM integrity check. Poisoning signal — do not swallow. */ declare class MemoryIntegrityError extends Error { readonly id: number; constructor(id: number, reason: string); } declare function syncLocalMemory(auth: AgentAuth, pointer: MemoryPointer, opts?: SyncMemoryOptions): Promise; declare class PointerStore { private readonly filePath; private cache; private loading; constructor(filePath: string); /** Resolves the pointer for `agentPubkeyHex`, or a zero-pointer that will force a sync on first use. */ get(agentPubkeyHex: string): Promise; /** Persists an updated pointer. Failures are swallowed to a logger callback (if provided) so sync never blocks the caller. */ set(agentPubkeyHex: string, pointer: MemoryPointer, onError?: (err: Error) => void): Promise; private ensureLoaded; private loadOnce; private persist; } /** Default pointer-file location — `/.atbash/memory-pointer.json`. */ declare function defaultPointerPath(workspaceDir?: string): string; /** Small logger shape used across the memory-poisoning surface. */ interface WrappedLogger { info(message: string, meta?: Record): void; warn(message: string, meta?: Record): void; } interface UpstreamLogger { info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; } /** Writes are serialized via an internal promise queue so lines interleave in call-order under concurrency. */ declare function createFileLogger(filePath: string, upstream?: UpstreamLogger): WrappedLogger; /** Default log-file location — `/.atbash/plugin.log`. */ declare function defaultPluginLogPath(workspaceDir?: string): string; /** Dedicated memory-read tool names, matched case-insensitively. */ declare const DEFAULT_MEMORY_READ_TOOL_NAMES: ReadonlyArray; interface ClassifyMemoryReadOptions { /** Tool names that always count as memory reads. Merged with defaults. */ readToolNames?: ReadonlyArray; /** Additional path substrings that mark a file as memory. Merged with defaults. */ patterns?: ReadonlyArray; /** Additional generic-read tool names whose path arg to inspect. Merged with defaults. */ genericReadToolNames?: ReadonlyArray; } /** * Returns `true` when this tool call is a memory read — either a * dedicated memory-read tool from `readToolNames`, or a generic read * tool (`read` / `read_file`) targeting a memory-shaped path. * * Caller-supplied `patterns` are MERGED with the defaults (matches * Node's original behavior — extending in one plugin doesn't disable * standard coverage). */ declare function classifyMemoryRead(event: unknown, ctx: unknown, opts?: ClassifyMemoryReadOptions): boolean; /** Decision the manager returns to the plugin's `before_tool_call` handler. */ interface HookDecision { allow?: boolean; block?: boolean; blockReason?: string; reason?: string; } interface MemoryGuardManagerOptions { auth: AgentAuth; /** Host workspace root (used to derive default file paths). */ workspaceDir: string; /** Absolute MEMORY.md path. Default `/MEMORY.md`. */ memoryFilePath?: string; /** Persistent pointer file. Default `/.atbash/memory-pointer.json`. */ pointerFilePath?: string; /** File-backed log. Default `/.atbash/plugin.log`. */ logFilePath?: string; /** Optional host-native logger — every event mirrors here as well. */ hostLogger?: { info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; }; /** TTL for the local-sync pointer between chain checks. Default 30_000 ms. */ ttlMs?: number; /** Block memory reads when the chain-active version's score is below this. Default 1 (never blocks). */ rollbackMinScore?: number; /** True → return `{block:true}` on defense triggers. False → log and return `null` (audit-only). Default true. */ enforce?: boolean; /** Host-specific tuning of what counts as a memory read. */ memoryReadClassifier?: ClassifyMemoryReadOptions; /** Passed through to `guardMemoryWrite`. Host memory-write tool names override. */ memoryWriteToolNames?: ReadonlyArray; /** Passed through to `guardMemoryWrite` — extra memory path substrings. */ memoryPathPatterns?: ReadonlyArray; /** Passed through to `guardMemoryWrite` — judge endpoint override (defaults to userConfig / DEFAULT_ENDPOINT). */ judgeEndpoint?: string; /** Passed through to `guardMemoryWrite` — self-hosted judge verify pubkey. */ judgeVerifyPubKey?: string; /** Passed through — org name for chain resolution. */ orgName?: string; /** Debug probe in `guardMemoryWrite`. */ debug?: boolean; } /** * Wire-once, dispatch-many factory. Plugins call once at register(), * then feed every `before_tool_call` through `handleBeforeToolCall`. */ declare class MemoryGuardManager { private readonly opts; private readonly pointerStore; private readonly logger; private readonly memoryFilePath; private readonly ttlMs; private readonly rollbackMinScore; private readonly enforce; private readonly agentPubkeyHex; constructor(opts: MemoryGuardManagerOptions); /** * One-shot chain probe at plugin registration. Refreshes MEMORY.md * from chain when drifted and score passes threshold. Fire-and-forget * — errors are logged, never thrown. */ runBootProbe(): Promise; /** * Returns a `HookDecision` when the event is a memory read or write * (host returns it verbatim to its runtime). Returns `null` when the * event isn't memory-related — host falls through to its own audit. */ handleBeforeToolCall(event: unknown, ctx: unknown): Promise; private mapGuardResult; private handleMemoryRead; private writeMemoryAtomic; } declare function createMemoryGuardManager(opts: MemoryGuardManagerOptions): MemoryGuardManager; /** * Atbash SDK Telemetry — OpenTelemetry metrics for usage tracking. * * Tracks: function call counts, latency, source (CLI/plugin/SDK), * and agent identity. ON by default. * * Opt-out: create ~/.config/atbash/telemetry.json with { "enabled": false } * The file must be readable by the SDK process. If missing, corrupted, or * unreadable → telemetry stays ON. Environment variables cannot disable * telemetry (prevents agent bypass via env-var injection). */ type ClientSource = "cli" | "sdk" | "plugin:openclaw" | "plugin:langchain" | "plugin:langgraph" | "plugin:hermes" | "plugin:eliza" | "plugin:crewai" | "plugin:mcp" | "plugin:autogen" | "plugin:jeenai" | (string & {}); interface TelemetryConfig { /** Must be true to send any telemetry. Default: false */ enabled: boolean; /** Where calls originate */ source?: ClientSource; /** Flush interval in ms. Default: 60000 */ exportIntervalMs?: number; } declare function setupTelemetry(config: TelemetryConfig): void; /** * Record a function call. Call at the START of each tracked function. * Safe to call even if telemetry is disabled — does nothing. */ declare function recordCall(functionName: string, source?: ClientSource, agentPubkey?: string): void; /** * Record function duration. Call at the END of each tracked function. * Safe to call even if telemetry is disabled — does nothing. */ declare function recordDuration(functionName: string, durationMs: number, status: "success" | "error", source?: ClientSource): void; /** * Force-flush pending metrics without shutting down. * Use in short-lived processes (CLI) to ensure data is sent. */ declare function flushTelemetry(): Promise; /** * Flush pending metrics and shut down. Call before process exits. */ declare function shutdownTelemetry(): Promise; /** * Rust core does the work; `browser/encrypted-toolcall.ts` mirrors it for the * browser and must produce the same columns. */ /** Must match `column_aad` in the core — the label binds a ciphertext to its column. */ declare function columnAad(toolCallId: string, column: string): string; /** Byte-identical to the dashboard's copy — diverging breaks hold-retry resolution. */ declare function normalizeActionForHash(action: string): string; /** Lets the judge check the request body against the ciphertext without an org key. */ declare function claimHashHex(toolName: string, action: string, context: string, toolArgsJson: string): string; /** @returns hex-encoded signed tx, ready to POST as `signed_log_tool_call`. */ declare function signEncryptedToolCall(toolCallId: string, action: string, context: string, toolName: string, toolArgsJson: string, orgEncryptionPubKey: string, privkeyHex: string, blockchainRidHex: string): string; /** * Cryptographic domain per payload kind. Each kind derives a distinct * key from the same handshake — a verdict payload handed to the * tool-call reader fails authentication rather than silently decoding. * * Values here are the SHORT domain names the Rust core recognizes. * The full HKDF `info` strings (`atbash:chain-encryption:v1:`) * live inside the core and never surface at the API boundary. */ declare const EciesDomain: { readonly toolCall: "toolcall"; readonly verdict: "verdict"; readonly note: "note"; readonly policy: "policy"; readonly raw: "raw"; }; type EciesDomain = (typeof EciesDomain)[keyof typeof EciesDomain]; /** * Encrypt `plaintext` so that only the holder of `orgPubKeyHex` can read it. * * @param plaintext UTF-8 text to protect. * @param orgPubKeyHex Org's compressed secp256k1 public key (33 bytes hex). * @param aad Context bound to the ciphertext — pass the record's id. * @returns raw payload for a Rell `byte_array` column. */ declare function encryptForOrg(plaintext: string, orgPubKeyHex: string, aad: string, domain?: EciesDomain): Uint8Array; /** * Decrypt a payload produced by {@link encryptForOrg}. * * Throws if the key is wrong, the `aad` does not match the one used at * encrypt time, or the ciphertext was tampered with — GCM authentication * makes all three indistinguishable by design. * * @param payload Value read from the on-chain `byte_array` column. * @param orgPrivKeyHex Org's secp256k1 private key (32 bytes hex). * @param aad Must equal the `aad` used when encrypting. */ declare function decryptForOrg(payload: Uint8Array, orgPrivKeyHex: string, aad: string, domain?: EciesDomain): string; /** * Size in bytes of the encrypted payload for a given plaintext length. * Lets callers check against the on-chain column cap * (`MAX_CONTENT_CIPHER_SIZE`) before submitting a transaction the * contract would reject. */ declare function encryptedLength(plaintextByteLength: number): number; /** * atb1... * * Normative spec: `core/src/crypto_envelope.rs`. This mirrors it for the browser. */ interface Envelope { /** First 8 bytes of the recipient public key, hex. May be empty. */ keyFingerprint: string; /** Commitment to the accompanying plaintext claims. May be empty. */ claimHash: string; /** Raw ECIES payload. */ payload: Uint8Array; } declare function packEnvelope(payload: Uint8Array, keyFingerprint?: string, claimHash?: string): string; /** * Stays true for a truncated envelope that `parseEnvelope` rejects — a severed * ciphertext is not plaintext, so callers must show a placeholder. */ declare function isEnvelope(value: string): boolean; /** Null, not a throw — pre-encryption records are plaintext. */ declare function parseEnvelope(value: string): Envelope | null; declare function keyFingerprintOf(pubKeyHex: string): string; declare function isValidPrivateKey(hex: string): boolean; declare function derivePublicKey(privkey: string): string; declare function generateKeypair(): KeyPair; declare function loadAgent(privkey: string): AgentAuth; declare function signLogToolCall(toolCallId: string, action: string, context: string, toolName: string, toolArgsJson: string, privkey: string, blockchainRid: string): string; declare function signJudgeAction(judgmentId: string, action: string, context: string, extra: string, privkey: string, blockchainRid: string): string; declare function verifySignature(body: Buffer, signatureHex: string, pubkeyHex: string): boolean; declare function normalizeForMatching(text: string): string; declare function containsEvasionCharacters(text: string): boolean; declare function redactSecrets(text: string): RedactResult; declare function containsSecret(text: string): boolean; declare function createMemorySnapshot(entries: MemoryEntry[], takenAt: number): MemorySnapshot; declare function diffMemorySnapshots(before: MemorySnapshot, after: MemorySnapshot): MemoryDiffResult; export { type ActionType, type AgentAuth, type AgentMemoryEntry, type AgentPolicy, type AnomalySeverity, type AnomalyType, Atbash, AtbashAPIError, type AtbashLogger, type AtbashOptions, type AtbashUserConfig, type ChainOpts, type ClassifierToolContext, type ClassifierToolEvent, type ClassifyMemoryReadOptions, type ClassifyMemoryWriteOptions, type ClientSource, type CommitMemoryOptions, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, DEFAULT_MEMORY_PATH_PATTERNS, DEFAULT_MEMORY_READ_TOOL_NAMES, DEFAULT_MEMORY_WRITE_TOOL_NAMES, type Decision, type DecisionVerdict, EciesDomain, type EncryptedMemory, type Envelope, type FromConfigOptions, type GuardLogger, type GuardMemoryDecision, type GuardMemoryWriteInput, type GuardMemoryWriteResult, type HeldAction, type HeldActionReview, type HookDecision, type JudgeEndpointConfig, type JudgeOptions, type JudgeResult, type JudgmentState, type JudgmentStatus, type KeyPair, type LogToolCallOptions, type LogToolCallResult, type MemoryAnomaly, type MemoryDiffResult, type MemoryEntry, MemoryGuardManager, type MemoryGuardManagerOptions, MemoryIntegrityError, type MemoryPointer, type MemoryRollbackEvent, type MemoryScanOptions, type MemoryScanResult, type MemoryScanVerdict, type MemorySnapshot, type ModifiedEntry, type Network, type OrgSubscription, PointerStore, type Provider, type PubkeyValue, type RedactResult, type RollbackMemoryOptions, type SecretKind, type SecretMatch, SignatureVerificationError, type Subscription, type SyncMemoryOptions, type SyncMemoryResult, type TelemetryConfig, type TierInfo, type ToolCallFull, type ToolCallInput, type ToolCallRecord, type ValidatedEndpoint, type Verdict, type WrappedLogger, buildAllowedJudgeHosts, claimHashHex, classifyMemoryRead, classifyMemoryWrite, columnAad, commitMemoryVersion, containsEvasionCharacters, containsSecret, createFileLogger, createMemoryGuardManager, createMemorySnapshot, decryptForOrg, decryptMemoryContent, defaultPluginLogPath, defaultPointerPath, deriveMemoryKey, derivePublicKey, diffMemorySnapshots, encryptForOrg, encryptMemoryContent, encryptedLength, flushTelemetry, generateKeypair, getActiveMemory, getActiveMemoryId, getAllAgentMemory, getConfigDir, getConfigPath, getMemoryById, getMemoryHistory, getRollbackHistory, guardMemoryWrite, isEnvelope, isValidPrivateKey, keyFingerprintOf, loadAgent, loadAgentFromFile, loadUserConfig, normalizeActionForHash, normalizeForMatching, normalizeStatus, normalizeVerdict, packEnvelope, parseEnvelope, pubkeyToHex, recordCall, recordDuration, redactJsonStrings, redactSecrets, resolve, resolveKeyPath, rollbackMemory, saveUserConfig, scanMemory, scanMemoryBatch, setupTelemetry, shutdownTelemetry, signEncryptedToolCall, signJudgeAction, signLogToolCall, syncLocalMemory, validateJudgeEndpoint, verifyJudgeResponseSignature, verifySignature };