import { WorkingStore, IdentityProvider, PublishResult, ReconcileResult, AuthEndpoints, UserAdminEndpoints, AuthorOption, DiagnosticRegistry, UserSummary, AuthorDirectory, Repair, DiagnosticCheck } from '@nanoesis/engine';

/**
 * Editor white-labelling storage (DESIGN §11, Phase B). This is the *editor app's*
 * own chrome, a custom top-left logo + name an operator sets, deliberately kept out
 * of the engine (which only compiles a site's data to data) and out of the site's
 * `ContentSource` (so it can never leak into the published output). It lives here, in
 * the host, behind a narrow port so a deploy can swap the file-backed store for a
 * blob/table one without touching the routes.
 *
 * The logo bytes and the name are stored separately so reading the cheap metadata
 * (for the `GET /api/branding` poll the login screen and top bar make) doesn't pull
 * the image down every time; the image is fetched once via `GET /api/branding/logo`.
 */
interface BrandingLogoMeta {
    readonly contentType: string;
    /** Epoch ms of the last logo write, used to cache-bust the logo URL. */
    readonly updatedAt: number;
}
interface BrandingState {
    /** Operator-set display name, or null to fall back to the built-in brand. */
    readonly name: string | null;
    /** Logo metadata, or null when no logo is set. */
    readonly logo: BrandingLogoMeta | null;
}
interface BrandingLogo {
    readonly bytes: Uint8Array;
    readonly contentType: string;
}
interface BrandingStore {
    /** Cheap metadata read (name + whether/when a logo exists); never the image bytes. */
    get(): Promise<BrandingState>;
    /** The logo image, or null when none is set. */
    getLogo(): Promise<BrandingLogo | null>;
    /** Set (or clear, with null) the display name. */
    setName(name: string | null): Promise<void>;
    /** Replace the logo image. */
    setLogo(bytes: Uint8Array, contentType: string): Promise<void>;
    /** Remove the logo image (revert to the built-in mark). */
    clearLogo(): Promise<void>;
}
/** An ephemeral in-process {@link BrandingStore}, for tests and ephemeral examples. */
declare class InMemoryBrandingStore implements BrandingStore {
    private readonly now;
    private name;
    private logo;
    private logoUpdatedAt;
    constructor(now?: () => number);
    get(): Promise<BrandingState>;
    getLogo(): Promise<BrandingLogo | null>;
    setName(name: string | null): Promise<void>;
    setLogo(bytes: Uint8Array, contentType: string): Promise<void>;
    clearLogo(): Promise<void>;
}
/**
 * A file-backed {@link BrandingStore} for the local example and small self-hosted
 * deploys. Metadata is a small JSON file (`{ name, logo: { contentType, updatedAt } }`)
 * written atomically (tmp + rename); the image is a sibling file. BOM-tolerant on read
 * (Windows / PowerShell-5 default). Bring your own store for blob/table persistence.
 */
declare class FileBrandingStore implements BrandingStore {
    private readonly metaPath;
    private readonly now;
    private readonly logoPath;
    constructor(metaPath: string, now?: () => number);
    private loadMeta;
    private saveMeta;
    get(): Promise<BrandingState>;
    getLogo(): Promise<BrandingLogo | null>;
    setName(name: string | null): Promise<void>;
    setLogo(bytes: Uint8Array, contentType: string): Promise<void>;
    clearLogo(): Promise<void>;
}

/**
 * The host's content API as a pure, framework-agnostic router. It reproduces the dev
 * server's contract (`packages/editor/dev/content-api.ts`) exactly, `/api/list`,
 * `/read`, `/exists`, `/write`, `/delete`, `/rename`, plus `/publish`, so the editor
 * client talks to it unchanged. Keeping it free of `@azure/functions` means it is
 * unit-tested in memory; the Functions glue (`functions.ts`) just maps the runtime's
 * request/response onto these types.
 */
interface ApiRequest {
    readonly method: string;
    /** URL pathname, e.g. "/api/list". */
    readonly path: string;
    readonly query: URLSearchParams;
    readonly getHeader: (name: string) => string | undefined;
    readonly body: () => Promise<Uint8Array>;
}
interface ApiResponse {
    readonly status: number;
    readonly headers?: Record<string, string>;
    readonly body?: string | Uint8Array;
}
interface ApiDeps {
    /** The editor working store (read + write/delete/rename), any {@link WorkingStore}. */
    readonly store: WorkingStore;
    /** Who is calling, gates every editing route (DESIGN §11). */
    readonly identity: IdentityProvider;
    /** Run the publish pipeline (host binds source/sink/purge). */
    readonly publish: () => Promise<PublishResult>;
    /**
     * Optional index-reconcile (DESIGN §11d): rebuild the working store's content index
     * from the keys actually present, recovering files that arrived by a path that
     * bypassed the index (the silent-bootstrap failure). When present, the router mounts
     * the admin-gated `POST /api/reconcile`. The host binds it because enumerating the
     * real key set needs the adapter's listing (`BlobContainer.list`), which the engine's
     * `BlobStore` deliberately lacks. Omitted on stores that cannot enumerate.
     */
    readonly reconcile?: () => Promise<ReconcileResult>;
    /**
     * Optional credential-management surface (DESIGN §11). When present, the router
     * mounts `/api/login`, `/api/refresh`, `/api/logout`, and `/api/auth/state`,
     * unauthenticated routes that bypass the editor-role check. Trusted-header /
     * gateway-style deployments leave this unset.
     */
    readonly authEndpoints?: AuthEndpoints;
    /**
     * Optional admin-only user-management surface (DESIGN §11, Phase B). When present,
     * the router mounts `/api/users` (list/create) and `/api/users/:id` (update/delete)
     * plus `/api/users/:id/password` (reset), all gated on the `admin` role. Omitted by
     * trusted-header / external-IdP providers, where users are managed upstream.
     */
    readonly userAdmin?: UserAdminEndpoints;
    /**
     * Optional editor white-labelling store (DESIGN §11, Phase B). When present, the
     * router mounts the *anonymous* reads `GET /api/branding` (`{ name, logoUrl }`) and
     * `GET /api/branding/logo` (the image, anonymous so the login screen is branded too),
     * plus the admin-gated writes `PUT /api/branding`, `POST`/`DELETE /api/branding/logo`.
     * When absent, the reads return the built-in defaults and writes 404.
     */
    readonly branding?: BrandingStore;
    /**
     * Optional author directory (DESIGN §6.11). When present, the router mounts
     * `GET /api/authors` (any editing role, bylines are public) returning the users a
     * byline can name as `{ name, user }`, for the editor's authors picker. Absent → the
     * route returns `[]` and the picker is guest-only. The host builds this from its user
     * store and feeds the *same* users to the compiler's `authorDirectory` at publish.
     */
    readonly authors?: () => Promise<readonly AuthorOption[]>;
    /**
     * Optional diagnostics + self-heal registry. When present, the router mounts the
     * admin-only `GET /api/admin/diagnostics` (run all probes, return findings) and
     * `POST /api/admin/diagnostics/repair` (run a named repair, return refreshed findings).
     * The registry is port-agnostic: it depends only on the engine's port contracts, so
     * adopters using their own adapters get the same diagnostics with no per-host wiring.
     * Hosts typically supply {@link buildDefaultDiagnostics}; omit on a deployment that
     * has no admin operator (an embedded read-only host).
     */
    readonly diagnostics?: DiagnosticRegistry;
}
/**
 * Dispatch one API request. The editor is private, so every route requires an editing
 * role (author/developer/admin); writes are further partitioned by path (DESIGN §11).
 * Every response then passes through {@link withDefaultHeaders} so that no `/api/*`
 * response is silently cached (DESIGN §13).
 */
declare function handleApi(deps: ApiDeps, req: ApiRequest): Promise<ApiResponse>;

/** The byline picker's options, display name + stable handle, sorted by display name. */
declare function authorOptions(users: readonly UserSummary[]): AuthorOption[];
/**
 * A sync directory resolving a stored `user` handle to its current display name, for the
 * compiler's `authorDirectory`. The compiler resolves synchronously, so snapshot a fresh
 * user list (an async `listUsers()`) into this map *before* each compile/publish.
 */
declare function authorDirectory(users: readonly UserSummary[]): AuthorDirectory;

/** A JSON Schema (2020-12 subset) for a tool's arguments. Plain data, no SDK types. */
interface JsonSchemaProperty {
    readonly type: 'string';
    readonly description?: string;
}
interface JsonSchemaObject {
    readonly type: 'object';
    readonly properties: Readonly<Record<string, JsonSchemaProperty>>;
    readonly required?: readonly string[];
    readonly additionalProperties: false;
}
/** A transport-neutral MCP tool definition the host registers with the SDK. */
interface McpToolDef {
    readonly name: string;
    readonly description: string;
    readonly inputSchema: JsonSchemaObject;
}
/** The outcome of a tool call, ready for the host to wrap in the SDK's result type. */
interface McpToolResult {
    readonly text: string;
    readonly isError: boolean;
}
/** Per-call options. The token threads the caller's identity for HTTP transports; a
 *  local stdio host with a pass-through identity omits it. */
interface McpCallOptions {
    readonly token?: string;
}
/** A read-only MCP resource definition (context the client can pull). */
interface McpResourceDef {
    readonly uri: string;
    readonly name: string;
    readonly description: string;
    readonly mimeType: string;
}
/** The catalog of MCP tools a host registers (the executable mapping is kept internal). */
declare const MCP_TOOLS: readonly McpToolDef[];
/**
 * Execute an MCP tool call by routing it through {@link handleApi}, so it is authenticated
 * and role-gated identically to the HTTP transport. An unknown tool name is a tool error,
 * not a thrown exception (the client surfaces it to the model).
 */
declare function callMcpTool(deps: ApiDeps, name: string, args?: Readonly<Record<string, unknown>>, options?: McpCallOptions): Promise<McpToolResult>;
/** The read-only resources a host exposes. The authoring reference is the keystone: the
 *  engine-generated, never-drifting syntax guide the model reads before authoring. */
declare const MCP_RESOURCES: readonly McpResourceDef[];
/** Resolve a resource URI to its contents, or `undefined` if the URI is unknown. */
declare function readMcpResource(uri: string): {
    readonly text: string;
    readonly mimeType: string;
} | undefined;

/**
 * The first-run starter site (DESIGN §14): a minimal, self-contained set of files that
 * turns an empty working store into a real, publishable site. It is the *blessed* way to
 * get initial content in — written through the editor API (so the content index stays
 * authoritative by construction, never the bypassing path that silently breaks a store,
 * §11d) and bundled here as **pure data**, so the engine's purity is untouched and the
 * scaffold works identically for every host and the MCP server with no per-host wiring.
 *
 * Auto-fires on first sign-in to an empty store (revised 2026-05-28). The earlier behaviour
 * — a confirm prompt that the user could dismiss — left a user who said no with no path
 * forward (the empty Content workspace has no signposted route to the Dev workspace, and
 * every alternative to scaffolding needs templates to already exist). Removing the choice
 * removes a concept; the scaffold is idempotent and gate-clean, so doing it always is safe.
 *
 * Deliberately minimal (revised 2026-05-28, owner's call):
 *   - `templates/home.html` is a **full HTML document** (DESIGN §6.10: with no
 *     `templates/document.html`, a page template is the whole document) — no shared shell.
 *     The user can extract one later when they add a second page; for the bootstrap state,
 *     three files is simpler than four.
 *   - `public/styles.css` for baseline readability — a one-page site without any CSS reads
 *     poorly, and the styles.css path is the editor's canonical "your site's CSS" location.
 *   - `content/index.json` with `isPublished: true` (revised 2026-05-28). The earlier
 *     "draft, so going live is deliberate" framing turned out to be a footgun: a new user
 *     would hit Publish and get the "nothing went live" warning without obvious cause. A
 *     published placeholder is honest about what a publish will do; the user's first edit
 *     is to replace the placeholder copy, not to also remember to toggle a flag.
 */
/**
 * The starter files, keyed by working-store path. Written through the store's `write`
 * (so the index records each). The store has no cross-file ordering requirement.
 */
declare const SCAFFOLD_FILES: Readonly<Record<string, string>>;

/**
 * The default {@link DiagnosticRegistry} the host mounts behind `/api/admin/diagnostics`.
 * Combines the engine's port-agnostic round-trip probe (works against any adapter) with
 * the scaffold-aware content checks that need to know what a "home template" is. The
 * editor-api layer is the right home for the latter: the engine has no opinion on what
 * paths matter, while the scaffold is bundled here as pure data (so MCP and every host
 * see the same set; see scaffold.ts).
 *
 * Returned registry is mutable — a host that needs site-specific checks can call `add` /
 * `addRepair` before mounting it.
 */
declare function buildDefaultDiagnostics(): DiagnosticRegistry;
/**
 * `templates/home.html` is the locked path the editor refuses to rename, move, or delete,
 * and the scaffold guarantees it on first run. A missing home template means the site has
 * no home page and no template to fall back to; restoring the bundled scaffold version is
 * a one-click fix (the page is just the user's content again, the template is what was
 * deleted out from under them — typically by a direct blob-store edit).
 */
declare const homeTemplateMissingDiagnostic: DiagnosticCheck;
/**
 * Restore `templates/home.html` from the bundled scaffold. Idempotent: if a customised
 * home template already exists this is a no-op, so a stale UI re-firing the repair never
 * silently overwrites real work. The home template is the only file the scaffold owns
 * as "the locked, blessed copy", so reset semantics are correct here.
 */
declare const recreateHomeTemplateRepair: Repair;
/**
 * A site with zero `isPublished: true` items publishes nothing — a common confused-user
 * state. We surface it as a warning (the publish still completes, just empty), not an
 * error, because the situation is legitimate during early authoring. No auto-repair: the
 * user picks what to publish; we only point out that nothing is.
 */
declare const noPublishedContentDiagnostic: DiagnosticCheck;
/**
 * Walk every published content item; for any pinned to a snapshot, check whether the
 * snapshot file exists and parses (PROPOSAL §16.1, §16.2). Emits one finding per
 * affected item — the missing-snapshot case (publish-blocking error) and the
 * corrupt-snapshot case (publish-blocking error, distinct headline so the user knows
 * "the file is there but the bytes are bad" vs "the file is gone"). Both repair via
 * `templates.rebind-item-to-current`.
 */
declare const templateSnapshotIntegrityDiagnostic: DiagnosticCheck;
/**
 * Rebind an item's `template` field from `<name>@v<N>` to `<name>` (current). Used for
 * the missing/corrupt snapshot repair: the item's pin is lost (the snapshot was the
 * intent), but the item itself stays, and shows up in the pending-migrations list so
 * its fields can be reconciled with current. Idempotent: a write of the same JSON is
 * a no-op semantically.
 */
declare const rebindItemToCurrentRepair: Repair;
/**
 * Snapshot exists but its current sibling is missing (PROPOSAL §16.4). Someone deleted
 * `templates/article.html` and left `templates/article@v1.html` behind. The Health page
 * surfaces this with the `copy-snapshot-to-current` repair — promotes the snapshot to
 * be the current.
 */
declare const templateSuffixConflictDiagnostic: DiagnosticCheck;
/**
 * Copy a snapshot's bytes to the current path (PROPOSAL §16.4 repair). The snapshot
 * itself remains in place; the user can retire it manually later. Idempotent: if the
 * current already exists, the repair is a no-op (so a stale UI re-firing the repair
 * never silently overwrites real work).
 */
declare const copySnapshotToCurrentRepair: Repair;
/**
 * Count items whose current-template binding has orphan fields (PROPOSAL §10). Read-only
 * summary — points the user at the Migrations workspace (Phase 2). No auto-repair, since
 * resolution is per-item (drop / rename / keep) and needs human choice.
 */
declare const pendingMigrationsDiagnostic: DiagnosticCheck;

export { type ApiDeps, type ApiRequest, type ApiResponse, type BrandingLogo, type BrandingLogoMeta, type BrandingState, type BrandingStore, FileBrandingStore, InMemoryBrandingStore, MCP_RESOURCES, MCP_TOOLS, type McpCallOptions, type McpResourceDef, type McpToolDef, type McpToolResult, SCAFFOLD_FILES, authorDirectory, authorOptions, buildDefaultDiagnostics, callMcpTool, copySnapshotToCurrentRepair, handleApi, homeTemplateMissingDiagnostic, noPublishedContentDiagnostic, pendingMigrationsDiagnostic, readMcpResource, rebindItemToCurrentRepair, recreateHomeTemplateRepair, templateSnapshotIntegrityDiagnostic, templateSuffixConflictDiagnostic };
