/** * Grants Vault — encrypted, per-subject grant storage for ident.agency SDK * ------------------------------------------------------------------------ * - Encrypts all grants client-side with AES-GCM (256) derived via HKDF * - Keys are derived from a root key (session KEK) provided after unlock * - Non-extractable CryptoKeys; in-memory only while unlocked * - Per-subject namespacing; AAD binds {subjectId, agentKey, schema} */ export type AgentIdentity = { kind: 'inline'; id: string; } | { kind: 'iframe'; id: string; origin: string; bundle_sha256?: string; }; export interface GrantCapabilities { read_lenses?: string[]; mutate_paths?: string[]; } export type Grant = { subject: string; agent: AgentIdentity; capabilities: GrantCapabilities; egress?: { allowed_hosts?: string[]; }; created_at: string; updated_at?: string; expires_at?: string | null; revoked?: boolean; }; export interface ListGrantsOptions { subjectId?: string; agentId?: string; agentKey?: string; } export type Subject = { id: string; displayName?: string; avatarUrl?: string; did?: string; }; export type AsyncKV = { get(key: string): Promise; set(key: string, val: string, ttlSec?: number): Promise; del(key: string): Promise; }; export declare class LockedError extends Error { constructor(msg?: string); } export type SubjectProvider = { getSubject(): Promise; }; /** Deterministic agent key for namespacing and AAD */ export declare function agentKeyOf(grant: Pick): string; /** Helper: parse agentKey back into agent identity */ export declare function parseAgentKey(k: string): Grant['agent']; /** * GrantsVault * =========== * * Purpose: * - Stores and protects **agent grants** (consent records) per subject. * - Grants define what lenses/paths an agent may access, but do not hold * or unlock the encrypted fragments themselves. * * Keys: * - GrantsVault has its own **root key** (per subject), derived and cached * only while unlocked. * - From this root, HKDF(salt=subjectId, info="ident.grants.v1") → AES-GCM key. * - That AES-GCM key (the "grantsKey") is used *only* to encrypt/decrypt * the grant JSON blobs stored in KV. * * Separation from Fragments: * - Private fragments are encrypted separately under the **User Keychain**. * - Unlocking the GrantsVault gives access to *which* paths an agent is allowed, * but does not give access to the **fragment decryption keys**. * - Actual fragment decryption flows: * User unlocks Keychain (password/passkey/device) → unwrap DEK → decrypt fragment. * * Why separate? * - Principle of least privilege: losing grantsKey reveals consent records, * but not sensitive data. * - Grants can be audited/revoked independently from encrypted fragments. * - UX: you can unlock grants vault for quick consent checks without forcing * full user keychain unlock. */ export declare class GrantsVault { private kv; private subjectProvider; private hkdfKey; private grantsKeyCache; private emit?; constructor(kv: AsyncKV, subjectProvider: SubjectProvider, emit?: (event: string, payload: any) => void); /** Unlock with raw root key material (stable per subject) */ unlockWithRawRootKey(rootKeyMaterial: ArrayBuffer | Uint8Array): Promise; /** Unlock with an existing HKDF CryptoKey (non-extractable) */ unlockWithHKDFKey(hkdfKey: CryptoKey): Promise; /** Lock: wipe key handles from memory */ lock(): void; isUnlocked(): boolean; /** Save or update a grant (encrypted) */ saveGrant(grant: Grant): Promise; /** Revoke (delete) a grant by agent identity */ revokeGrant(subjectId: string, agent: AgentIdentity): Promise; /** Load a grant by agent identity */ loadGrant(agent: Grant['agent']): Promise; /** List all decrypted grants for current (or provided) subject */ listGrants(opts?: ListGrantsOptions): Promise; private getGrantsKeyForSubject; } //# sourceMappingURL=grants-vault.d.ts.map