/**
 * Generic subscriber registry for broadcasting to SSE clients.
 *
 * Supports channel-based filtering — subscribers connect with optional
 * channel filters, and broadcasts reach only matching subscribers.
 *
 * Two identity slots enable both targeted disconnection and per-scope cap
 * enforcement:
 * - `scope` — a single capped identity (e.g., session hash). Subject to
 *   the per-scope cap and matched by `close_by_identity`. Use for the
 *   narrowest identity the subscriber belongs to.
 * - `groups` — any number of uncapped identities (e.g., account id).
 *   Matched by `close_by_identity` but not subject to any cap. Use for
 *   coarser scopes a stream should be reachable by.
 *
 * The split keeps "tabs-per-session" cap semantics sane when a stream also
 * carries a broader identity for coarse close — the broader identity
 * doesn't cap across sessions.
 *
 * @module
 */
import type { SseStream } from './sse.js';
export interface Subscriber<T> {
    stream: SseStream<T>;
    /** Channels this subscriber listens to. `null` means all channels. */
    channels: Set<string> | null;
    /** Primary (capped) identity. `null` when none. */
    scope: string | null;
    /** Grouping identities for `close_by_identity`. `null` when none. */
    groups: Set<string> | null;
}
/** Options for `SubscriberRegistry`. */
export interface SubscriberRegistryOptions {
    /**
     * Max subscribers sharing a single `scope`. On subscribe, when the count
     * of subscribers with the same `scope` reaches this limit, the oldest
     * matching subscriber(s) are closed before the new one is added.
     * `null` (default) disables the cap. `groups` identities are never capped.
     */
    max_per_scope?: number | null;
}
/** Options for `SubscriberRegistry.subscribe`. */
export interface SubscribeOptions {
    /** Channels to subscribe to. Empty/absent = all channels. */
    channels?: ReadonlyArray<string>;
    /**
     * Primary (capped) identity — e.g., session hash. Subject to
     * `max_per_scope` and matched by `close_by_identity`.
     */
    scope?: string;
    /**
     * Grouping identities — e.g., account id. Matched by `close_by_identity`
     * but NOT subject to the cap. Use for coarse-targeted close.
     */
    groups?: ReadonlyArray<string>;
}
/**
 * Generic subscriber registry with channel-based filtering and identity-keyed disconnection.
 *
 * Subscribers connect with optional channel filters, a capped `scope`, and
 * uncapped `groups`. Broadcasts go to a specific channel and reach only
 * matching subscribers. `close_by_identity` force-closes all subscribers
 * whose `scope` or `groups` contain the given key — use for auth revocation.
 *
 * @example
 * ```ts
 * const registry = new SubscriberRegistry<SseNotification>();
 *
 * // subscriber connects (from SSE endpoint)
 * const unsubscribe = registry.subscribe(stream, {channels: ['runs']});
 *
 * // when a run changes
 * registry.broadcast('runs', {method: 'run_created', params: {run}});
 *
 * // subscriber disconnects
 * unsubscribe();
 * ```
 *
 * @example
 * ```ts
 * // scope = session hash (capped), groups = [account id] (close-only)
 * const unsubscribe = registry.subscribe(stream, {
 *   channels: ['audit_log'],
 *   scope: session_hash,
 *   groups: [account_id],
 * });
 *
 * // coarse — close all of a user's streams on role revocation
 * registry.close_by_identity(account_id);
 *
 * // fine — close just the stream(s) tied to a specific session
 * registry.close_by_identity(session_hash);
 * ```
 */
export declare class SubscriberRegistry<T> {
    #private;
    constructor(options?: SubscriberRegistryOptions);
    /** Number of active subscribers. */
    get count(): number;
    /**
     * Add a subscriber.
     *
     * @param stream - SSE stream to send data to
     * @param options - channel filter and identity slots (`scope` + `groups`)
     * @returns unsubscribe function
     * @mutates registry - adds the new subscriber; closes oldest matching subscribers when `max_per_scope` is exceeded
     */
    subscribe(stream: SseStream<T>, options?: SubscribeOptions): () => void;
    /**
     * Broadcast data to all subscribers on a channel.
     *
     * Subscribers with no channel filter receive all broadcasts.
     * Subscribers with a channel filter only receive matching broadcasts.
     */
    broadcast(channel: string, data: T): void;
    /**
     * Force-close all subscribers whose `scope` or `groups` match the given key.
     *
     * Closes each matching stream and removes the subscriber from the registry.
     * Use for auth revocation — when a user's permissions change, close their
     * SSE connections so they must reconnect and re-authenticate.
     *
     * @param identity - the identity key to match (checked against `scope` and `groups`)
     * @returns the number of subscribers closed
     * @mutates registry - removes matching subscribers and closes their streams
     */
    close_by_identity(identity: string): number;
}
//# sourceMappingURL=subscriber_registry.d.ts.map