/**
 * DemoChannelRegistry — the §5.3 isolation backbone of the live-user-channel-proof
 * standard (docs/specs/live-user-channel-proof-standard.md §5.3 "Demo Channel
 * Isolation").
 *
 * A volatile / permission / dangerous live-test scenario must NEVER touch the live
 * operator channel — it runs only on a registered DEMO channel (a throwaway Slack
 * workspace, a demo Telegram group). The LiveTestHarness enforces this structurally
 * by calling `isDemoChannel(surface, channelId)` and refusing the whole run (a throw,
 * not a convention) if a non-safe scenario points at a channel this registry does not
 * vouch for.
 *
 * The bindings are SIGNED and read once. A binding set that fails signature
 * verification (tampered, unsigned, wrong signer) is FAIL-CLOSED: every channel
 * resolves to NOT-a-demo-channel, so the harness's §5.3 guard refuses every volatile
 * scenario rather than trusting an unverified "this is a safe demo channel" claim.
 * Fail-closed is the safe direction here — the cost of a false "not demo" is a refused
 * test; the cost of a false "is demo" is a destructive scenario on the live channel.
 *
 * This module is pure/injectable: it takes the raw bindings document + a `verify`
 * function (Ed25519, same signer surface the LiveTestArtifactStore uses) so it is
 * unit-testable with no filesystem or crypto host.
 */
import type { Surface } from './LiveTestArtifactStore.js';
/** One registered demo channel. `workspaceId` is Slack-only (the demo workspace). */
export interface DemoChannelBinding {
    surface: Surface;
    /** Slack channel id, Telegram chat/topic id (as a string), or dashboard id. */
    channelId: string;
    /** Slack workspace / team id — REQUIRED for slack, ignored otherwise. */
    workspaceId?: string;
    /** Human label for audit (e.g. "SageMind Live Test"). */
    label?: string;
}
/** The on-disk, signed bindings document. */
export interface DemoChannelBindingsDoc {
    version: 1;
    /** The machine that authored these bindings (audit only). */
    machineId: string;
    bindings: DemoChannelBinding[];
    signedAt: string;
    /** Ed25519 signature over the canonical payload (see canonicalBindingsPayload). */
    signature: string;
}
export interface DemoChannelRegistryDeps {
    /** The raw bindings document (e.g. parsed from state/demo-channel-bindings.json), or null when none exist. */
    doc: DemoChannelBindingsDoc | null;
    /** Verify a signature over a canonical payload string. Returns true iff valid. */
    verify: (payload: string, signature: string) => boolean;
    logger?: (m: string) => void;
}
/**
 * The exact bytes the signature covers. Stable, order-independent across the binding
 * LIST (sorted) so a re-serialization can't change the signed payload, but the
 * signature is otherwise over the full meaningful content (version + machineId +
 * signedAt + every binding field). Any field change invalidates the signature.
 */
export declare function canonicalBindingsPayload(doc: Omit<DemoChannelBindingsDoc, 'signature'>): string;
export declare class DemoChannelRegistry {
    private readonly verified;
    private readonly set;
    private readonly d;
    constructor(deps: DemoChannelRegistryDeps);
    private key;
    private log;
    /** True iff (surface, channelId) is a verified, registered demo channel. */
    isDemoChannel(surface: Surface, channelId: string): boolean;
    /** Whether a present bindings doc verified (false when none exist OR signature failed). */
    get isVerified(): boolean;
    /** Count of registered demo channels (0 when unverified/absent). */
    get size(): number;
}
//# sourceMappingURL=DemoChannelRegistry.d.ts.map