import type { DerivedPrivateJwk, DwnConfig, EncryptionKeyDeriver, GenericMessage, ProtocolDefinition } from '@enbox/dwn-sdk-js';
import type { PublicKeyJwk } from '@enbox/crypto';
import { Dwn } from '@enbox/dwn-sdk-js';
import type { EnboxPlatformAgent } from './types/agent.js';
import type { LocalDwnStrategy } from './local-dwn.js';
import type { DwnResponse, ProcessDwnRequest, SendDwnRequest } from './types/dwn.js';
import { DwnInterface } from './types/dwn.js';
export { isDwnMessage, isDwnRequest, isMessagesPermissionScope, isRecordPermissionScope, isRecordsType } from './dwn-type-guards.js';
type DwnApiParams = {
    agent?: EnboxPlatformAgent;
    localDwnStrategy?: LocalDwnStrategy;
} & ({
    dwn: Dwn;
    localDwnEndpoint?: never;
} | {
    dwn?: never;
    localDwnEndpoint: string;
});
interface DwnApiCreateDwnParams extends Partial<DwnConfig> {
    dataPath?: string;
}
export declare class AgentDwnApi {
    /**
     * Holds the instance of a `EnboxPlatformAgent` that represents the current execution context for
     * the `AgentDwnApi`. This agent is used to interact with other Enbox agent components. It's vital
     * to ensure this instance is set to correctly contextualize operations within the broader Enbox
     * Agent framework.
     */
    private _agent?;
    /**
     * The DWN instance to use for this API.
     * `undefined` in remote mode — all operations route through RPC to
     * the local DWN server endpoint.
     */
    private readonly _dwn?;
    /**
     * The local DWN server endpoint for remote mode.
     * When set, `_dwn` is `undefined` and `processRequest()` routes
     * through `sendDwnRpcRequest()`.
     */
    private readonly _localDwnEndpoint?;
    /**
     * Protocol definition cache — TTL 30 minutes. Protocols rarely change.
     * Keyed by `${tenantDid}~${protocolUri}`.
     */
    private readonly _protocolDefinitionCache;
    /**
     * Context key cache — stores resolved context encryption key info for
     * multi-party protocols. Keyed by rootContextId. TTL 30 minutes.
     */
    private readonly _contextKeyCache;
    /**
     * Context-derived private key cache — stores DerivedPrivateJwk for contexts
     * where the current user is a participant (not the creator).
     * Keyed by `ctx~${authorDid}~${rootContextId}`. TTL 30 minutes.
     */
    private readonly _contextDerivedKeyCache;
    /**
     * Delegate decryption key cache — stores scope-aware decryption keys
     * delivered to delegates during the connect flow. These keys enable
     * delegates to decrypt encrypted records without possessing the owner's
     * root X25519 private key.
     *
     * Keyed by `ddk~${delegateDid}`. Each entry is an array covering all
     * granted read scopes for that delegate session.
     * TTL 24 hours (keys are re-populated on session restore).
     */
    private readonly _delegateDecryptionKeyCache;
    /**
     * Delegate context key cache — stores ProtocolContext decryption keys for
     * multi-party encrypted protocols. Each key is scoped to one rootContextId.
     * Keyed by `dctx~${delegateDid}~${protocol}~${rootContextId}`.
     * TTL 24 hours (re-populated on session restore).
     */
    private readonly _delegateContextKeyCache;
    /** Tracks which context key cache entries belong to which delegate DID. */
    private readonly _delegateContextKeyCacheIndex;
    /**
     * Explicit registry of which multi-party protocols each delegate has
     * protocol-wide read-like access to. Populated at connect time (even
     * when zero contexts exist) and used by postWriteKeyDelivery() to
     * decide whether to deliver new context keys.
     *
     * Keyed by delegateDid. Each entry is a Set of protocol URIs.
     * Unlike the context key cache, this registry is NOT time-limited —
     * it persists for the lifetime of the session.
     */
    private readonly _delegateMultiPartyProtocols;
    /**
     * Optional callback invoked when post-connect context keys are delivered
     * to a delegate. The auth layer sets this to persist updated keys.
     */
    private _onDelegateContextKeysChanged?;
    /**
     * Cache of locally-managed DIDs (agent DID + identities). Used to decide
     * whether a target DID should be routed through the local DWN server.
     */
    private readonly _localManagedDidCache;
    /** Controls local DWN discovery behavior ('prefer' | 'only' | 'off'). */
    private _localDwnStrategy;
    /** Lazy-initialized local DWN discovery instance. */
    private _localDwnDiscovery?;
    /**
     * Tracks fire-and-forget eager-send promises dispatched by
     * `writeContextKeyRecord`. The set is consumed by `drainPendingEagerSends()`
     * during test-harness teardown so orphan promises cannot outlive the agent
     * and touch closed LevelDB handles or nulled state.
     *
     * Entries auto-remove on settlement via the `.finally` attached in
     * `trackEagerSend`.
     */
    private readonly _pendingEagerSends;
    constructor(params: DwnApiParams);
    /**
     * Whether the API is operating in remote mode (no in-process DWN).
     * In remote mode, all DWN operations are routed through RPC.
     */
    get isRemoteMode(): boolean;
    /**
     * Retrieves the `EnboxPlatformAgent` execution context.
     *
     * @returns The `EnboxPlatformAgent` instance that represents the current execution context.
     * @throws Will throw an error if the `agent` instance property is undefined.
     */
    get agent(): EnboxPlatformAgent;
    set agent(agent: EnboxPlatformAgent);
    get localDwnStrategy(): LocalDwnStrategy;
    setLocalDwnStrategy(strategy: LocalDwnStrategy): void;
    /**
     * Inject a cached local DWN endpoint (e.g. from a `dwn://connect`
     * browser redirect or from persisted storage). The endpoint is validated
     * via `GET /info` before being accepted.
     *
     * @param endpoint - The local DWN server base URL.
     * @returns `true` if the endpoint was validated and cached, `false` otherwise.
     * @see https://github.com/enboxorg/enbox/issues/589
     */
    setCachedLocalDwnEndpoint(endpoint: string): Promise<boolean>;
    /**
     * Resolves the DWN service endpoint URLs for the given target DID, optionally
     * prepending a local DWN server endpoint when local discovery is enabled and
     * the target is a locally-managed DID.
     *
     * @param targetDid - The DID whose DWN endpoints should be resolved.
     * @returns An array of endpoint URLs.
     * @throws When strategy is `'only'` and no local server is available.
     */
    getDwnEndpointUrlsForTarget(targetDid: string): Promise<string[]>;
    /**
     * Returns only the DWN service endpoints from the DID document (no local
     * discovery endpoint). Use this when you need to confirm that a message
     * reached the owner's actual remote DWN, not just the delegate's local server.
     */
    getRemoteDwnEndpointUrls(targetDid: string): Promise<string[]>;
    /** Lazily retrieves the local DWN server endpoint via discovery. */
    private getLocalDwnEndpoint;
    /**
     * Attempt to create a {@link DwnDiscoveryFile} for file-based local DWN
     * discovery. Returns `undefined` in environments where the filesystem
     * is not available (e.g. browsers).
     */
    private static _tryCreateDiscoveryFile;
    /**
     * Determines whether the given target DID should be routed through the
     * local DWN server. Returns `true` if the DID is the agent DID or one
     * of the locally-managed identity DIDs.
     */
    private shouldUseLocalDwnForTarget;
    /**
     * Public getter for the DWN instance used by this API.
     *
     * Notes:
     * - This getter is public to allow advanced developers to access the DWN instance directly.
     *   However, it is recommended to use the `processRequest` method to interact with the DWN
     *   instance to ensure that the DWN message is constructed correctly.
     * - The getter is named `node` to avoid confusion with the `dwn` property of the
     *   `EnboxPlatformAgent`. In other words, so that a developer can call `agent.dwn.node` to access
     *   the DWN instance and not `agent.dwn.dwn`.
     */
    get node(): Dwn;
    static createDwn({ dataPath, dataStore, didResolver, stateIndex, eventLog, messageStore, tenantGate, resumableTaskStore }: DwnApiCreateDwnParams): Promise<Dwn>;
    processRequest<T extends DwnInterface>(request: ProcessDwnRequest<T>): Promise<DwnResponse<T>>;
    /**
     * Process a pre-constructed DWN message against the local DWN (in-process
     * or remote server). Used by the sync engine to store messages that were
     * already fetched from a remote DWN.
     *
     * Unlike {@link processRequest}, this method does NOT construct a new
     * message — it takes an already-signed `GenericMessage` and routes it
     * to the appropriate backend.
     *
     * @param tenant - The DID of the DWN tenant (target).
     * @param message - The pre-constructed DWN message.
     * @param options - Optional data stream and subscription handler.
     * @returns The reply from processing the message.
     */
    processRawMessage(tenant: string, message: GenericMessage, options?: {
        dataStream?: ReadableStream<Uint8Array>;
    }): Promise<{
        status: {
            code: number;
            detail: string;
        };
    }>;
    sendRequest<T extends DwnInterface>(request: SendDwnRequest<T>): Promise<DwnResponse<T>>;
    /**
     * Post-write key delivery: after a successful encrypted `RecordsWrite`,
     * detect new participants and write `contextKey` records so they can
     * decrypt records in the context.
     *
     * This is a non-fatal operation — if participant detection or key delivery
     * fails, the record is still stored and a warning is logged.
     */
    private postWriteKeyDelivery;
    private sendDwnRpcRequest;
    private constructDwnMessage;
    private hasGrantParams;
    private getSigner;
    /**
     * Constructs an EncryptionKeyDeriver callback for the SDK.
     * Delegates to the standalone function in `dwn-encryption.ts`.
     *
     * @param didUri - The DID URI to create the key deriver for
     * @returns An EncryptionKeyDeriver callback object
     */
    getEncryptionKeyDeriver(didUri: string): Promise<EncryptionKeyDeriver>;
    /**
     * Resolves the keyAgreement verification method for the given DID and returns
     * the key ID, key URI, and public key JWK.
     *
     * @param didUri - The DID URI to look up
     */
    private getEncryptionKeyInfo;
    /**
     * Constructs a ProtocolPath KeyDecrypter for the given DID.
     *
     * @param didUri - The DID URI to build a decrypter for
     */
    private getKeyDecrypter;
    /**
     * Analyses a record write to determine which DIDs need context key delivery.
     *
     * @param params - Parameters for participant detection
     * @returns Set of DIDs that need context key delivery
     */
    detectNewParticipants(params: {
        protocolDefinition: ProtocolDefinition;
        protocolPath: string;
        recipient?: string;
        tenantDid: string;
        authorDid?: string;
    }): Set<string>;
    /**
     * Fetches a protocol definition from the local DWN, with caching.
     * Returns undefined if the protocol is not installed.
     *
     * @param tenantDid - The tenant DID to query
     * @param protocolUri - The protocol URI to fetch
     * @returns The protocol definition, or undefined if not found
     */
    private getProtocolDefinition;
    /**
     * Fetches a protocol definition from a remote DWN.
     * Uses an unsigned ProtocolsQuery (public protocols can be queried anonymously).
     */
    private fetchRemoteProtocolDefinition;
    /**
     * Extracts the `derivedPublicKey` from an existing ProtocolContext-encrypted
     * record in a context on a remote DWN. This key allows an external author to
     * encrypt new records in the same context without knowing the context private key.
     *
     * @param targetDid      - The DWN owner's DID
     * @param protocolUri    - The protocol URI to search
     * @param rootContextId  - The root context ID
     * @param requesterDid   - The DID of the requester (used for signing the query)
     * @returns The rootKeyId and derivedPublicKey, or undefined if no ProtocolContext
     *          record exists yet
     */
    private extractDerivedPublicKey;
    /**
     * Post-processes a DWN reply, auto-decrypting data if encryption is enabled.
     * Delegates to the standalone function in `dwn-encryption.ts`.
     */
    private maybeDecryptReply;
    private getDwnMessage;
    /**
     * Cache for key delivery protocol installation status per tenant.
     * Once confirmed installed, we skip re-checking for 21 days.
     */
    private readonly _keyDeliveryProtocolInstalledCache;
    /**
     * Ensures the key delivery protocol is installed on the given tenant's DWN,
     * with `$encryption` keys injected.
     *
     * @param tenantDid - The DID of the DWN owner
     */
    ensureKeyDeliveryProtocol(tenantDid: string): Promise<void>;
    /**
     * Imports scope-aware decryption keys for delegate sessions.
     *
     * Called during the connect flow when the wallet delivers decryption keys
     * for encrypted protocols. Keys are derived only for read-like scopes
     * (Read/Query/Subscribe) — write-only delegates receive no keys.
     *
     * The keys are cached and used by `resolveKeyDecrypter()` to decrypt
     * records when the delegate does not possess the owner's root X25519
     * private key.
     *
     * @param delegateDid - The delegate DID for this session (unique per connect)
     * @param keys - Array of scope-aware decryption key entries
     */
    /**
     * Sets a callback invoked whenever post-connect context keys are
     * delivered to a delegate. The auth layer uses this to persist
     * updated context keys so they survive restart.
     *
     * @param callback - Called with the delegateDid that received new keys.
     *                   Set to `undefined` to unregister.
     */
    set onDelegateContextKeysChanged(callback: ((delegateDid: string) => void) | undefined);
    importDelegateDecryptionKeys(delegateDid: string, keys: {
        protocol: string;
        scope: {
            kind: 'protocol';
        } | {
            kind: 'protocolPath';
            protocolPath: string;
            match: 'exact';
        };
        derivedPrivateKey: DerivedPrivateJwk;
    }[]): void;
    /**
     * Imports ProtocolContext decryption keys for multi-party encrypted protocols.
     * Each key is scoped to one rootContextId within one protocol.
     *
     * @param delegateDid - The delegate DID for this session
     * @param keys - Array of `{ protocol, contextId, derivedPrivateKey }` entries
     */
    importDelegateContextKeys(delegateDid: string, keys: {
        protocol: string;
        contextId: string;
        derivedPrivateKey: DerivedPrivateJwk;
    }[], multiPartyProtocols?: string[]): void;
    /**
     * Clears all delegate decryption keys (both ProtocolPath and ProtocolContext)
     * from the in-memory cache. Called on disconnect to prevent stale keys from
     * persisting across sessions.
     *
     * @param delegateDid - If provided, clears keys for that delegate session only.
     *                      If omitted, clears all delegate keys.
     */
    clearDelegateDecryptionKeys(delegateDid?: string): void;
    /**
     * Exports the current set of delegate context keys for a specific delegate.
     * Returns an array of `{ protocol, contextId, derivedPrivateKey }` entries
     * suitable for serialization and persistence.
     *
     * Called by the auth layer to persist context keys (including keys delivered
     * post-connect) so they survive agent restarts.
     *
     * @param delegateDid - The delegate DID whose context keys to export
     * @returns Array of context key entries (may be empty)
     */
    exportDelegateContextKeys(delegateDid: string): {
        protocol: string;
        contextId: string;
        derivedPrivateKey: DerivedPrivateJwk;
    }[];
    /**
     * Exports the registered multi-party protocol URIs for a delegate.
     * Used by the auth layer for persistence.
     */
    exportDelegateMultiPartyProtocols(delegateDid: string): string[];
    /**
     * Checks whether any active delegate session has context keys for the
     * given protocol. Used by `postWriteKeyDelivery()` to determine if
     * delegate delivery is needed.
     */
    private hasEligibleDelegatesForProtocol;
    /**
     * Delivers a newly created multi-party context key to all active delegate
     * sessions that have existing context keys for the given protocol.
     *
     * This is same-process delivery: the context key is injected directly
     * into `_delegateContextKeyCache`. It works when the delegate cache is
     * on the same agent instance that creates the root record.
     *
     * Cross-device DWN-based delivery (where the owner's agent and the
     * delegate's agent are separate processes) is a documented follow-up.
     *
     * @param protocol - The protocol URI
     * @param rootContextId - The root context ID of the new context
     * @param contextKey - The derived context key (`DerivedPrivateJwk`)
     */
    private deliverContextKeyToDelegates;
    /**
     * Delivers a newly created multi-party context key to eligible delegates
     * by writing `contextKey` records to the owner's DWN via the key-delivery
     * protocol. This enables cross-device delivery: the delegate can later
     * fetch the record from the owner's DWN and decrypt it.
     *
     * Eligible delegates are discovered by querying the owner's DWN for
     * active permission grants with read-like scopes on the given protocol.
     *
     * The contextKey record is encrypted using the delegate's pre-derived
     * key-delivery leaf public key, which is stored in the grant's tags
     * during `submitConnectResponse()`.
     *
     * @param tenantDid - The owner's DID
     * @param protocol - The protocol URI
     * @param rootContextId - The root context ID of the new context
     * @param contextKey - The derived context key (`DerivedPrivateJwk`)
     */
    private deliverContextKeyToDelegatesViaDwn;
    /**
     * Registers a fire-and-forget eager-send promise in the in-flight tracker so
     * it can be awaited by `drainPendingEagerSends()` during teardown. The entry
     * auto-removes on settlement via `.finally`.
     *
     * The promise is returned **unchanged** so callers can still chain `.catch`
     * on it for observability (e.g. the existing `console.warn` on failure).
     *
     * @param p - The eager-send promise to track. Must always resolve (callers
     *   are expected to attach a `.catch` handler before passing).
     * @returns The same `p`, unchanged.
     */
    private trackEagerSend;
    /**
     * Waits for all currently-tracked eager-send promises to settle. Used by
     * the test harness during teardown (`clearStorage()`/`closeStorage()`) to
     * prevent orphan promises from touching closed stores or nulled state.
     *
     * Snapshot semantics: awaits only the sends tracked at the moment of
     * invocation. Sends registered **after** this call begins are not joined
     * into its drain — a subsequent `drainPendingEagerSends()` is needed to
     * await them.
     *
     * Fast path: when no sends are tracked, resolves immediately without
     * invoking `Promise.allSettled([])`.
     *
     * @returns A promise that resolves to `undefined` once all snapshotted
     *   sends have settled. Never rejects (uses `allSettled` semantics).
     */
    drainPendingEagerSends(): Promise<void>;
    /**
     * Writes a `contextKey` record to the owner's DWN, delivering an encrypted
     * context key to a participant.
     *
     * @param params - The write parameters
     * @returns The recordId of the written contextKey record
     */
    writeContextKeyRecord(params: {
        tenantDid: string;
        recipientDid: string;
        contextKeyData: DerivedPrivateJwk;
        sourceProtocol: string;
        sourceContextId: string;
        recipientKeyDeliveryPublicKey?: {
            rootKeyId: string;
            publicKeyJwk: PublicKeyJwk;
        };
    }): Promise<string>;
    /**
     * Eagerly sends a contextKey record to the tenant's remote DWN.
     * This is best-effort — sync guarantees eventual consistency regardless.
     */
    private eagerSendContextKeyRecord;
    /**
     * Fetches and decrypts a `contextKey` record from a DWN, returning the
     * `DerivedPrivateJwk` payload.
     *
     * @param params - The fetch parameters
     * @returns The decrypted `DerivedPrivateJwk`, or `undefined` if no matching record found
     */
    fetchContextKeyRecord(params: {
        ownerDid: string;
        requesterDid: string;
        sourceProtocol: string;
        sourceContextId: string;
    }): Promise<DerivedPrivateJwk | undefined>;
}
//# sourceMappingURL=dwn-api.d.ts.map