import type { IsoTime, NodeIdDTO } from './common.js'; export type CronScopeDTO = 'profile' | 'global'; export type CronOverlapDTO = 'skip' | 'queue' | 'replace'; export type CronOnOutputDTO = 'silent' | 'on-failure' | 'always' | 'on-change'; export type CronStateDTO = 'active' | 'paused'; export type CronRunStateDTO = 'idle' | 'running'; /** Is this a safe single path segment for `routes.cron*()` interpolation? * Cron ids are server-minted UUIDs, but the route builders carry no logic, so * every interpolated id is gated here first (the `isSafeNodeId` discipline). */ export declare function isSafeCronId(id: string): boolean; /** The last settled run, carried on every cron projection so `cron list` shows * recent health without a `cron show` per row. Null until the first run. */ export interface CronLastRunDTO { /** When the run settled (UTC). */ finished: IsoTime | null; /** -1 = timeout kill; null = no exit observed (process error / skip marker). */ exit_code: number | null; /** What the sink did with the output, or why it didn't. */ delivered: string | null; } /** A cron row projection (`GET /v1/crons`). */ export interface CronDTO { cron_id: string; /** Agent-legible label; how the cron shows in list. */ name: string; /** Provenance only — the node that armed it, if any; never a cascade anchor. */ created_by: NodeIdDTO | null; /** The bash command each fire runs. */ command: string; /** Next occurrence (UTC). */ fire_at: IsoTime; /** Recur JSON (interval or cron); null for a one-shot. */ recur: string | null; /** IANA zone for a calendar cadence; null otherwise. */ tz: string | null; /** Clock bound; the row is deleted when passed. Null = no bound. */ expires_at: IsoTime | null; /** Opt-in node coupling (cascades on that node's deletion); null = detached. */ anchor_node: NodeIdDTO | null; cancel_on_wake: boolean; /** Execution context, snapshotted at arm time. */ cwd: string; profile: string | null; scope: CronScopeDTO; /** Names of the extra env vars snapshotted onto the row — KEYS ONLY: the * values are the caller's to know and may be secrets. */ env_keys: string[]; run_timeout_s: number; overlap: CronOverlapDTO; on_output: CronOnOutputDTO; /** Where deliveries go — the raw sink spec (`node:` | `spawn:` | * `human`), or null when the disposition never delivers. */ sink: string | null; tier: string; state: CronStateDTO; run_state: CronRunStateDTO; /** Recent health: the most recent settled run, or null if it never ran. */ last_run: CronLastRunDTO | null; created: IsoTime; updated: IsoTime; } /** `GET /v1/crons` query. `profile` is the CALLER's profile, which is what * scoping means here: a profile-scoped cron belongs to its profile, a global * one is canvas-home-wide. Omitting `profile` means the caller stands outside * every profile (a plain shell, or a provenance read such as "which crons did * node X arm") and sees the whole canvas home. This is a namespacing * boundary between profiles, not a security boundary. */ export interface ListCronsQuery { profile?: string; } /** Caller identity for the per-cron routes (show/pause/resume/run/cancel). * Same rule as `ListCronsQuery`: a cron outside the caller's scope is 404, * and an absent profile sees everything. */ export interface CronScopeQuery { profile?: string | null; } /** One settled run-log entry (`GET /v1/crons/:cronId`, `POST /v1/crons/:cronId/run`). */ export interface CronRunDTO { run_id: string; started: IsoTime; finished: IsoTime | null; duration_ms: number | null; /** null = no exit observed (spawn/process error, or a skip marker); -1 = timeout kill. */ exit_code: number | null; stdout_head: string | null; stderr_head: string | null; /** What the sink did with this run's output, or why it didn't. */ delivered: string | null; } /** `GET /v1/crons/:cronId` — one cron with its run-log ring (most recent first). */ export interface CronShowDTO { cron: CronDTO; runs: CronRunDTO[]; } /** `POST /v1/crons` — arm one cron. The CLI resolves timing client-side * (parseWhen/parseCadence) and sends the settled `fire_at`/`recur`/`tz`; * the server mints the cron_id and applies spec defaults for everything * omitted. */ export interface ArmCronRequest { name: string; command: string; fire_at: IsoTime; recur?: string | null; tz?: string | null; created_by?: NodeIdDTO | null; /** Execution context, snapshotted at arm time — chosen by the client, else * inherited from the creating node; never re-resolved at run time. */ cwd: string; /** Extra env for every run, as a JSON object of string values. */ env_json?: string | null; profile?: string | null; /** `profile` (default when a profile is resolved) requires a profile. */ scope?: CronScopeDTO; on_output?: CronOnOutputDTO; /** Raw sink spec: `node:` | `spawn:` | `human`. Required by the * always/on-change dispositions; meaningless otherwise. */ sink?: string | null; tier?: string; expires_at?: IsoTime | null; anchor_node?: NodeIdDTO | null; cancel_on_wake?: boolean; run_timeout_s?: number; overlap?: CronOverlapDTO; }