/**
 * `InboundRouter` — AUTO.6 inbound-channel dispatcher.
 *
 * Authoritative source: `docs/tasks/automation.md` AUTO.6. Walks the user's
 * `RoutingConfig.channelMapping`, finds the adapter for each concrete URI,
 * and (when the adapter implements `subscribeInbound`) attaches a per-
 * abstract-channel listener. Inbound messages flow:
 *
 *   adapter.subscribeInbound(handler)
 *     → handler(event)
 *       → CapabilityGate.check(pack, 'send_message', sender)   [optional]
 *         → if allowed → dispatch(event)
 *         → if denied  → audit + drop
 *
 * Sender allowlist is intentionally enforced via the existing AUTO.3
 * capability gate (`send_message` capability with `channels:` allowlist
 * — repurposed for inbound: a sender ID is the principal, mapped against
 * the same pack-declared list). The router does NOT introduce a new gate
 * surface; reuse keeps audit + override semantics identical.
 *
 * Engine-vocabulary: emits `InboundChannelEvent` only; never knows what
 * downstream evaluator does with the event.
 *
 * Imports from: ../runtime/event.js, ../runtime/capability_gate.js,
 * ./types.js. Imported by: src/runtime/daemon.ts (later) + tests.
 */
import type { InboundChannelEvent } from '../runtime/event.js';
import type { CapabilityGate } from '../runtime/capability_gate.js';
import type { ChannelAdapter, RoutingConfig } from './types.js';
/**
 * Per-abstract-channel inbound binding. Each binding maps one abstract
 * channel name (e.g. `'alerts'`) to the pack that listens on it. Multiple
 * packs can listen on the same abstract channel — declare one binding per
 * (pack, channel) pair.
 */
export interface InboundBinding {
    /** Pack id — passed to `CapabilityGate.check` as the principal. */
    pack: string;
    /** Abstract channel name — looked up in `routing.channelMapping`. */
    channel: string;
}
export type InboundDispatcher = (event: InboundChannelEvent) => Promise<void>;
interface AuditCommon {
    pack: string;
    channel: string;
}
export type InboundRouterAuditEntry = (AuditCommon & {
    event: 'inbound_subscribed';
    uri: string;
    scheme: string;
}) | (AuditCommon & {
    event: 'inbound_unmapped';
}) | (AuditCommon & {
    event: 'inbound_no_adapter';
    scheme: string;
}) | (AuditCommon & {
    event: 'inbound_adapter_not_inboundable';
    uri: string;
    scheme: string;
}) | (AuditCommon & {
    event: 'inbound_dispatched';
    uri: string;
    sender: string;
}) | (AuditCommon & {
    event: 'inbound_sender_denied';
    sender: string;
    reason: string;
}) | (AuditCommon & {
    event: 'inbound_dispatch_error';
    sender: string;
    reason: string;
});
export type InboundRouterAuditSink = (entry: InboundRouterAuditEntry) => void;
export interface InboundRouterOpts {
    /** Optional capability gate. When set, every inbound event runs through
     *  `gate.check({pack, capability: 'send_message', target: sender})`
     *  BEFORE dispatch. Denial drops the event + audits. Unset → no
     *  sender filtering (dev/test default). */
    capabilityGate?: CapabilityGate;
    auditLog?: InboundRouterAuditSink;
}
export declare class InboundRouter {
    private readonly subscriptions;
    private readonly auditLog;
    private readonly capabilityGate;
    private state;
    constructor(opts?: InboundRouterOpts);
    /**
     * Walk `bindings`, resolve each abstract channel → URI via
     * `routing.channelMapping`, look up the adapter by URI scheme, and call
     * its `subscribeInbound` to attach a sender-gated dispatcher. Skips +
     * audits any binding whose channel is unmapped, whose adapter scheme
     * isn't registered, or whose adapter doesn't implement `subscribeInbound`.
     *
     * Idempotent: a second `start()` while already running throws so the
     * caller surfaces a lifecycle bug rather than double-subscribing.
     */
    start(bindings: readonly InboundBinding[], routing: RoutingConfig, adapters: Map<string, ChannelAdapter>, dispatch: InboundDispatcher): Promise<void>;
    /**
     * Unsubscribe every active binding in reverse order. Idempotent — a
     * second stop() is a no-op. Each unsubscribe is best-effort; failures
     * are swallowed so a single bad adapter doesn't strand the rest.
     */
    stop(): Promise<void>;
    /** Test/inspection — number of active subscriptions. */
    activeSubscriptionCount(): number;
    private handleInbound;
}
export {};
//# sourceMappingURL=inbound_router.d.ts.map