import type { Kysely } from "kysely";
import type { ILogger } from "document-model";
import { OBSERVABILITY_PULL_USER_AGENT } from "../vetra-housekeeping/policy.js";
export type ClintServiceTuple = {
    documentId: string;
    prefix: string;
    subdomain: string;
    /** Served at the env apex (`<subdomain>.vetra.io`) — a sole-CLINT Studio. */
    isApex: boolean;
    /** Current per-service status from the read-model (e.g. PROVISIONING/ACTIVE). */
    status?: string | null;
};
export type ClintPullWorkerConfig = {
    /** Processor's namespace DB — has the `environments` table. */
    envDb: Kysely<any>;
    /** Observability DB — has `clint_runtime_endpoints`. */
    obsDb: Kysely<any>;
    logger: ILogger;
    /** Defaults to 15000ms. */
    intervalMs?: number;
    /**
     * Maps a CLINT service tuple to its `/_proxy/routes` URL.
     * Defaults to the flattened single-label host (apex: `<subdomain>.vetra.io`,
     * else `<subdomain>-<prefix>.vetra.io`) + `/_proxy/routes`.
     * Overridable for tests.
     */
    buildAgentUrl?: (service: ClintServiceTuple) => string;
    /**
     * Maps a studio service to its switchboard GraphQL URL (for the BrandSheet
     * pull). Defaults to `https://<agent-host>/switchboard/graphql`. Overridable
     * for tests (which serve a mock over http).
     */
    buildBrandUrl?: (service: ClintServiceTuple) => string;
    /** Per-fetch timeout. Defaults to 5000ms. */
    fetchTimeoutMs?: number;
    /**
     * Dispatch a document action on an env doc (mirrors the processor's own
     * `reactorClient.execute` helper). Used to advance a CLINT service
     * PROVISIONING → ACTIVE once its website endpoint is live. Optional: when
     * absent (e.g. tests that don't exercise it) the worker only does discovery.
     */
    dispatch?: (documentId: string, type: string, input: Record<string, unknown>) => Promise<void>;
};
export { OBSERVABILITY_PULL_USER_AGENT };
export declare class ClintPullWorker {
    private readonly config;
    private timer;
    private readonly buildAgentUrl;
    private readonly buildBrandUrl;
    private readonly fetchTimeoutMs;
    /**
     * Envs (`documentId|prefix`) we've already dispatched SET_SERVICE_STATUS→ACTIVE
     * for this pod lifetime. Attempt-once guard: without it, a mutation that never
     * commits (times out / a pathological doc whose replay overflows the stack)
     * leaves the read-model status at PROVISIONING, so the advance re-fired every
     * tick → reactor job-queue flood → heap OOM → switchboard crashloop. One
     * attempt per env per lifetime bounds it; a genuinely-transient failure retries
     * on the next pod restart (rare, acceptable).
     */
    private readonly statusAdvanceAttempted;
    constructor(config: ClintPullWorkerConfig);
    start(): void;
    stop(): void;
    tickOnce(): Promise<void>;
    /**
     * Fetch the studio's BrandSheet and cache name/maxim/concept in `studio_brand`
     * so /user/products shows the real product name even after the studio sleeps.
     * No-clobber: an empty/waking/failed response leaves the last cached row.
     */
    private pullBrand;
    private listClintServices;
    private pullOne;
    /**
     * Advance a CLINT service PROVISIONING → ACTIVE the first time its live
     * website endpoint is discovered. The env-doc's per-service status is what the
     * post-creation "provisioning" screen polls, and nothing else advances it — so
     * a cold-created (BYOK) studio would otherwise spin on "provisioning" forever
     * even though its agent is serving (warm-claimed studios sidestep this because
     * the claim redirects straight in). Guarded on the current status so it fires
     * exactly once, not on every 15s tick. Never throws: a transient dispatch
     * failure just retries next tick.
     */
    private maybeMarkServiceActive;
    private upsert;
}
//# sourceMappingURL=clint-pull-worker.d.ts.map