/**
 * Browser Secondary Defense (opt-in lockdown)
 *
 * Background
 * ----------
 * The Node.js secondary defense layer (DefenseInDepthBox) relies on
 * `node:async_hooks` AsyncLocalStorage to scope global monkey-patches to the
 * async context of a single `bash.exec()` call. AsyncLocalStorage does not
 * exist in browsers, so in browser builds the entire DefenseInDepthBox is a
 * no-op (its `IS_BROWSER` guard early-returns everywhere). That means the
 * browser bundle ships `Function`, `eval`, and `Proxy` fully live.
 *
 * IMPORTANT context on the actual risk:
 * - The PRIMARY architectural defense still holds in the browser: ag-bash has
 *   no bash -> JavaScript escape hatch. Bash scripts are lexed, parsed, and
 *   interpreted; there is no path from a bash command to `eval`/`Function`.
 * - This module provides the missing SECONDARY depth layer for the browser: a
 *   process-wide, opt-in hardening pass that freezes JavaScript intrinsics so
 *   that even if a future bug or a malicious host-supplied custom command tried
 *   to reach a dynamic-code primitive, the surrounding environment cannot be
 *   mutated to mount a prototype-pollution or intrinsic-hijacking escape.
 *
 * Why a lighter freeze instead of SES `lockdown()`?
 * - SES (`ses` package) is the gold-standard approach (full Compartment model
 *   + frozen realm). However it adds a runtime dependency and meaningfully
 *   changes global semantics (it freezes `Date`, `Math.random` determinism
 *   shims, taming of `Error`, etc.) which can break legitimate host code that
 *   shares the realm with ag-bash. Per the v6.0.0 risk posture we ship the
 *   lighter intrinsic-freeze here and flag SES as a documented follow-up
 *   (see SECURITY.md). The freeze approach is fully reversible-free (we never
 *   mutate values, only flip writability/extensibility) and is gated so it does
 *   not run unless the host explicitly opts in.
 *
 * This file lives under `src/security/` which is exempt from the
 * banned-pattern scanner. It deliberately references `Function`, `eval`, and
 * `Proxy` for detection/freezing purposes only — it never *invokes* them.
 */
/**
 * Result of a hardening pass. Immutable snapshot describing what was frozen and
 * what (if anything) could not be frozen.
 */
export interface BrowserHardeningResult {
    /** True if hardening ran to completion (even if some best-effort freezes failed). */
    readonly applied: boolean;
    /** True if this call actually performed work; false if hardening was already applied. */
    readonly firstRun: boolean;
    /** Human-readable list of intrinsic paths that were frozen. */
    readonly frozen: readonly string[];
    /** Human-readable list of intrinsic paths that could not be frozen (best-effort). */
    readonly failures: readonly string[];
}
/**
 * Options for {@link hardenBrowserGlobals}.
 */
export interface BrowserHardeningOptions {
    /**
     * When true, also freeze `globalThis` itself (no new globals can be added).
     * This is the strictest setting and can break code that lazily attaches
     * globals (some polyfills do this). Default: false.
     */
    readonly freezeGlobalThis?: boolean;
    /**
     * Callback invoked once per intrinsic that could not be frozen. Useful for
     * surfacing environment-specific limitations without throwing.
     */
    readonly onFailure?: (path: string, reason: string) => void;
}
/**
 * Apply the browser secondary defense: freeze JavaScript intrinsics so the
 * shared realm cannot be mutated to mount a prototype-pollution or
 * intrinsic-hijacking escape.
 *
 * This is OPT-IN. Hosts that embed ag-bash in a browser and want Node-parity
 * secondary depth should call this ONCE, as early as possible (before any
 * untrusted code or any `bash.exec()`), typically right after import:
 *
 * ```ts
 * import { Bash, hardenBrowserGlobals } from "@ag-bash/bash/browser";
 * hardenBrowserGlobals();
 * const bash = new Bash();
 * ```
 *
 * Characteristics:
 * - Idempotent: safe to call multiple times; only the first call does work.
 * - Non-destructive: only flips writability/extensibility via `Object.freeze`;
 *   it never replaces or deletes any value, so no behavior is silently swapped.
 * - Fail-open per-intrinsic: a freeze that cannot be applied is reported in
 *   `failures` rather than throwing, so legitimate use is never broken.
 *
 * Pair this with a strict Content-Security-Policy that forbids inline/eval'd
 * script (see SECURITY.md) for true defense-in-depth at the browser layer.
 *
 * @param options - Optional hardening tuning. See {@link BrowserHardeningOptions}.
 * @returns Immutable {@link BrowserHardeningResult} describing the pass.
 */
export declare function hardenBrowserGlobals(options?: BrowserHardeningOptions): BrowserHardeningResult;
/**
 * Report whether {@link hardenBrowserGlobals} has been applied in this realm.
 */
export declare function isBrowserHardened(): boolean;
/**
 * Test-only: reset the module guard. Does NOT un-freeze anything (freezing is
 * irreversible); it only clears the bookkeeping flag so a fresh
 * `hardenBrowserGlobals()` call re-reports `firstRun: true`. Used by the test
 * suite to assert idempotency behavior deterministically.
 */
export declare function __resetBrowserHardeningForTests(): void;
