/**
 * @file Runtime config storage.
 *
 * # The `globalThis.__actuateConfig` contract (audit issue M8)
 *
 * The Actuate handler factory stashes the resolved CMS config on
 * `globalThis.__actuateConfig` so that every downstream module
 * (actions, plugins, page-builder, auth) can read it without a
 * dependency-injected handle. This is intentionally a single-process
 * mutable global, with these constraints:
 *
 * 1. **One config per process.** A given Node / Edge isolate runs exactly
 *    one Actuate CMS instance. Calling `handleActuateAPI({ config })`
 *    twice with different configs in the same process is unsupported and
 *    will silently overwrite. (If you need multi-tenant per-request
 *    configs, fork at the request layer — not via `globalThis`.)
 *
 * 2. **Set once at boot, read everywhere after.** Plugins and feature
 *    code MUST treat the returned object as read-only. Mutating it after
 *    boot will change behaviour for every subsequent request and is a
 *    common source of "phantom" bugs.
 *
 * 3. **Serverless cold starts re-init.** On Vercel / Lambda each cold
 *    start invokes `handleActuateAPI()` again, which re-reads the
 *    consumer's `actuate.config.ts` and re-stashes the global. There is
 *    no cross-instance synchronisation — assume per-isolate isolation.
 *
 * 4. **Tests reset between suites.** Vitest gives each test file its own
 *    Node worker with a fresh `globalThis`, but tests *within* a file
 *    share state. If your test mutates the config global, restore it in
 *    `afterEach`. The pattern is documented in
 *    `page-builder/__tests__/blocks.test.ts`.
 *
 * # Why `globalThis` and not React Context / dependency injection?
 *
 *   - The code paths that need the config (Prisma actions, server-side
 *     guards, plugin hooks) are not React-rendered and have no natural
 *     prop-drilling path.
 *   - Threading a config handle through every public API would be a
 *     breaking change for every consumer.
 *   - Global state is acceptable here because the config IS global per
 *     process by definition (point 1).
 *
 * If we ever migrate off `globalThis` (e.g. to AsyncLocalStorage for
 * multi-tenant), the consumer-facing `getActuateConfig()` API stays the
 * same — only this file changes. That's why every reader goes through
 * the helper instead of touching `globalThis` directly.
 */
import type { ActuateCMSConfig } from './types.js';
/**
 * The runtime view of an Actuate CMS config. The handler factory enriches
 * the user's `defineConfig({...})` object with internal caches (e.g.
 * `_pluginHooks`) and consumers may register experimental top-level fields
 * (e.g. `redirects`, custom plugin sub-configs) before the schema is ready.
 *
 * We keep the public shape strongly typed via `ActuateCMSConfig` and add a
 * permissive index signature for the runtime extras. Callers that need a
 * field defined on `ActuateCMSConfig` get full type safety; callers reaching
 * into runtime-only fields are forced to acknowledge they are off-schema by
 * narrowing themselves.
 */
export type RuntimeActuateConfig = ActuateCMSConfig & {
    /** Internal cache of plugin lifecycle hooks. Populated by the handler. */
    _pluginHooks?: unknown[];
    /** Forward-compat slot for runtime-registered extensions. */
    [key: string]: unknown;
};
/**
 * Read the per-process Actuate CMS config that `handleActuateAPI()` stashed
 * on `globalThis`. Returns `undefined` when no config has been registered
 * yet (e.g. during early test setup or when the API handler has never been
 * invoked).
 *
 * **Why a helper instead of reading `globalThis.__actuateConfig` directly?**
 * - Centralizes the unsafe cast so we never sprinkle `as any` across the
 *   codebase. If the storage strategy ever moves off `globalThis` (issue M8
 *   from the engineering audit), only this file changes.
 * - Gives every caller the same typed handle, which makes mocking in tests
 *   straightforward (set the global once, all readers see it).
 *
 * **Mutability warning:** the returned object is the *same reference* the
 * platform handler holds. Callers must not mutate it. For mutations (e.g.
 * a plugin registering a new collection at init time), use the platform's
 * own plugin lifecycle — not this getter.
 */
export declare function getActuateConfig(): RuntimeActuateConfig | undefined;
/**
 * Register the running config on `globalThis`. Only the platform-level API
 * handler should call this; plugins and feature code should read the config
 * via `getActuateConfig()` instead.
 */
export declare function setActuateConfig(config: RuntimeActuateConfig | ActuateCMSConfig): void;
/**
 * Read the cms-core version that was stamped onto `globalThis` at handler
 * init. Used by `/api/cms/health` and the `/updates/check` endpoint.
 */
export declare function getActuateCoreVersion(): string | undefined;
export declare function setActuateCoreVersion(version: string): void;
//# sourceMappingURL=runtime.d.ts.map