/**
 * Remote Secure Server — the secrets-holding side.
 *
 * Runs as an HTTP server (localhost or remote). Holds secrets and only
 * communicates through encrypted channels established via mutual auth.
 *
 * This server:
 *   - Authenticates incoming MCP proxy clients via Ed25519 signatures
 *   - Establishes encrypted channels via X25519 ECDH + AES-256-GCM
 *   - Receives encrypted tool requests, injects secrets, executes, encrypts results
 *   - Never exposes secrets in plaintext over the wire
 *   - Maintains an audit log of all operations
 *   - Rate-limits requests per session
 */
import express from 'express';
import { type RemoteServerConfig, type ResolvedRoute } from '../shared/config.js';
import { EncryptedChannel, type PublicKeyBundle } from '../shared/crypto/index.js';
import { HandshakeResponder, type HandshakeInit } from '../shared/protocol/index.js';
import { IngestorManager } from './ingestors/index.js';
/** An authorized peer with its alias and optional display name */
export interface AuthorizedPeer {
    /** Caller alias — the key from the callers config object */
    alias: string;
    /** Human-readable name for audit logs */
    name?: string;
    /** The peer's public keys (signing + exchange) */
    keys: PublicKeyBundle;
}
export interface Session {
    channel: EncryptedChannel;
    /** Caller alias for this session (from the matched AuthorizedPeer) */
    callerAlias: string;
    /** Per-caller resolved routes for this session */
    resolvedRoutes: ResolvedRoute[];
    createdAt: number;
    lastActivity: number;
    requestCount: number;
    /** Requests in the current rate-limit window */
    windowRequests: number;
    windowStart: number;
}
export interface PendingHandshake {
    responder: HandshakeResponder;
    init: HandshakeInit;
    createdAt: number;
}
/** Sanitized session projection — never includes channel keys or resolved
 *  routes (which carry decrypted secrets). Returned by getSessionsSnapshot()
 *  for the read-only /admin API. */
export interface SessionSnapshot {
    /** First 12 chars of the session ID — enough to disambiguate, doesn't
     *  expose enough material to forge or replay encrypted requests. */
    sessionIdShort: string;
    callerAlias: string;
    createdAt: number;
    lastActivity: number;
    requestCount: number;
    windowRequests: number;
    windowStart: number;
}
/** Loopback guard — used by /sync/listen, /sync/status, /events/stream, /admin.
 *  Hoisted to module scope so the admin router and its tests can reuse it. */
export declare function requireLoopback(req: express.Request, res: express.Response, next: express.NextFunction): void;
export declare function isEndpointAllowed(url: string, patterns: string[]): boolean;
export { resolvePlaceholders } from '../shared/config.js';
/**
 * Find the first route whose allowedEndpoints match the given URL.
 * Routes with empty allowedEndpoints match nothing.
 */
export declare function matchRoute(url: string, routes: ResolvedRoute[]): ResolvedRoute | null;
export declare function checkRateLimit(session: Pick<Session, 'windowRequests' | 'windowStart'>, limit: number): boolean;
export declare const SESSION_TTL: number;
export declare const HANDSHAKE_TTL: number;
export declare function cleanupSessions(sessionsMap: Map<string, Pick<Session, 'lastActivity'>>, pendingMap: Map<string, Pick<PendingHandshake, 'createdAt'>>, now?: number): {
    expiredSessions: string[];
    expiredHandshakes: string[];
};
/**
 * Project the active sessions into a sanitized snapshot for read-only use.
 *
 * Drops `channel` (holds AES keys) and `resolvedRoutes` (carry decrypted
 * secrets). Used by the loopback /admin API; never call res.json(session).
 */
export declare function getSessionsSnapshot(): SessionSnapshot[];
/** A file attachment transmitted as base64 data through the encrypted channel. */
export interface FileAttachment {
    /** Form field name (e.g., "files[0]", "file", "attachment") */
    field: string;
    /** Base64-encoded file content */
    data: string;
    /** Filename for the upload */
    filename: string;
    /** MIME type (e.g., "image/png", "application/pdf") */
    contentType: string;
}
export interface ProxyRequestInput {
    method: string;
    url: string;
    headers?: Record<string, string>;
    body?: unknown;
    /** File attachments — triggers multipart/form-data encoding */
    files?: FileAttachment[];
    /** Form field name for the JSON body part (default: "payload_json") */
    bodyFieldName?: string;
}
export interface ProxyRequestResult {
    status: number;
    statusText: string;
    headers: Record<string, string>;
    body: unknown;
}
/**
 * Core proxy request execution — route matching, secret injection, and fetch.
 *
 * Used by:
 * - The remote server's `http_request` tool handler (this file)
 * - callboard's `LocalProxy` class (in-process, no encryption)
 *
 * Pure in the sense that it takes routes as input rather than reading global state.
 * The only side effect is the outbound fetch().
 */
export declare function executeProxyRequest(input: ProxyRequestInput, routes: ResolvedRoute[]): Promise<ProxyRequestResult>;
/** Context passed to every tool handler, providing caller identity and shared services. */
export interface ToolContext {
    /** The caller alias for the session making this request. */
    callerAlias: string;
    /** The shared ingestor manager (for poll_events / ingestor_status). */
    ingestorManager: IngestorManager;
    /** Re-resolve routes for all sessions belonging to this caller.
     *  Call after secrets or connection list changes. */
    refreshRoutes: () => void;
}
/** Options for creating the app — allows dependency injection for tests */
export interface CreateAppOptions {
    /** Override config instead of loading from disk */
    config?: RemoteServerConfig;
    /** Override key bundle instead of loading from disk */
    ownKeys?: import('../shared/crypto/index.js').KeyBundle;
    /** Override authorized peers instead of loading from disk */
    authorizedPeers?: AuthorizedPeer[];
    /** Override the ingestor manager instead of creating one from config */
    ingestorManager?: IngestorManager;
    /** Disable per-IP rate limiting (for tests that make many requests from localhost) */
    disableRateLimiting?: boolean;
}
export declare function createApp(options?: CreateAppOptions): import("express-serve-static-core").Express;
export declare function main(): void;
//# sourceMappingURL=server.d.ts.map