/** * Shared direct-route definitions for REST-only HTTP endpoints. * * Operation-backed REST endpoints are modeled by `RestBinding` instances. * These seven endpoints stay direct because they describe or expose the HTTP * server itself rather than a durable workflow operation: * - `GET /v1/health` — anonymous liveness probe (no catalog op) * - `GET /v1/metrics` — Prometheus text exposition (text/plain, no catalog op) * - `GET /.well-known/api-catalog` — RFC 9264 service-desc linkset * - `GET /.well-known/mcp.json` — MCP transport discovery * - `GET /asyncapi.json` — transport-meta endpoint (self-describing, no catalog op) * - `GET /openapi.json` — transport-meta endpoint (self-describing, no catalog op) * - `GET /openrpc.json` — transport-meta endpoint (self-describing, no catalog op) * * @module server/route-model */ /** * External URL prefix under which the functional HTTP/WebSocket API is served * (REST workflows/schedules/tasks, `/mcp`, `/jsonrpc`, and the workflow/task * WebSocket upgrades). Optional dashboard shells can be mounted at specific * root-level page routes, so the API is namespaced beneath this prefix on the * wire. * * This is purely an *external* (wire) concern. Internal routing — the * `DIRECT_HTTP_ROUTES` table, every `RestBinding`, the WebSocket-upgrade * regexes, and the authentication allowlist — stays canonical and * root-relative. The HTTP front door strips this prefix from incoming requests * before any matching runs, and the spec/discovery generators reattach it via * {@link externalApiPath} when advertising endpoints. * * Root-stable surfaces are deliberately **not** moved under this prefix: * `/v1/health`, `/v1/metrics`, `/openapi.json`, `/openrpc.json`, * `/asyncapi.json`, and `/.well-known/*` remain at the origin root per * RFC 9264 / discovery convention. */ export declare const API_PREFIX = "/api"; /** Root-relative namespace for the functional REST and WebSocket API. */ export declare const ROOT_API_PREFIX = "/v1"; /** * Map a canonical, root-relative server path to its external (`/api`-prefixed) * form for emission in specs and discovery documents. * * Requires a leading slash and refuses an already-prefixed path so callers can * never produce `/api/api/...`. * * @example * ```ts * import { externalApiPath } from './route-model.ts'; * externalApiPath('/v1/workflows'); // '/api/v1/workflows' * externalApiPath('/mcp'); // '/api/mcp' * ``` */ export declare function externalApiPath(canonicalPath: string): string; /** HTTP method for a route. */ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; export type DirectRouteResponseMediaType = 'application/json' | 'application/msgpack' | 'application/linkset+json' | 'text/plain'; export type DirectRouteResponseSchema = 'object' | 'string'; export type DirectRouteResponseContent = { /** Media type advertised for this response body. */ mediaType: DirectRouteResponseMediaType; /** Minimal OpenAPI schema shape for this response body. */ schema: DirectRouteResponseSchema; }; export type DirectRouteResponse = { /** HTTP status emitted by the direct route. */ status: number; /** Human-readable response description for OpenAPI. */ description: string; /** Response body variants advertised by the direct route, when it has a body. */ content?: readonly DirectRouteResponseContent[]; }; export type DirectRouteAccess = 'public' | 'authenticated'; /** A single direct HTTP route definition. */ export type DirectHttpRouteDefinition = { /** HTTP method. */ method: HttpMethod; /** * Express-style path pattern (e.g. `/v1/workflows/:id/signal/:name`). * Used to generate OpenAPI path items and regex patterns. */ path: string; /** Internal handler function name. */ handler: string; /** Ordered list of path parameter names. */ paramNames: string[]; /** Human-readable summary for OpenAPI. */ summary: string; /** OpenAPI tags for grouping. */ tags: string[]; /** Response metadata shared by dispatch documentation. */ responses: readonly DirectRouteResponse[]; /** Direct route access policy for authentication and OpenAPI metadata. */ access: DirectRouteAccess; }; /** * Intentionally REST-only routes. These are not in the operation catalog. * * `as const` preserves the literal types of `handler` so consumers can * derive a string-literal union for compile-time exhaustiveness on route * executors. */ export declare const DIRECT_HTTP_ROUTES: readonly [{ readonly method: "GET"; readonly path: "/v1/health"; readonly handler: "healthCheck"; readonly paramNames: []; readonly summary: "Health check"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "Service health status"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }, { readonly mediaType: "application/msgpack"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/v1/metrics"; readonly handler: "getMetrics"; readonly paramNames: []; readonly summary: "Prometheus metrics export"; readonly tags: ["Observability"]; readonly responses: readonly [{ readonly status: 200; readonly description: "Prometheus metrics exposition"; readonly content: readonly [{ readonly mediaType: "text/plain"; readonly schema: "string"; }]; }, { readonly status: 503; readonly description: "Metrics exporter failure"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/.well-known/api-catalog"; readonly handler: "apiCatalog"; readonly paramNames: []; readonly summary: "RFC 9264 API catalog linkset"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "RFC 9264 API catalog linkset"; readonly content: readonly [{ readonly mediaType: "application/linkset+json"; readonly schema: "object"; }]; }, { readonly status: 421; readonly description: "Request host rejected by trustedHosts"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }, { readonly status: 503; readonly description: "API catalog origin is not configured"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/.well-known/mcp.json"; readonly handler: "mcpDiscovery"; readonly paramNames: []; readonly summary: "MCP discovery document"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "MCP transport discovery document"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }, { readonly status: 421; readonly description: "Request host rejected by trustedHosts"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }, { readonly status: 503; readonly description: "MCP discovery origin is not configured"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/openapi.json"; readonly handler: "openApiDocument"; readonly paramNames: []; readonly summary: "OpenAPI 3.1 specification"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "OpenAPI 3.1 specification"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/openrpc.json"; readonly handler: "openRpcDocument"; readonly paramNames: []; readonly summary: "OpenRPC 1.3.2 specification"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "OpenRPC 1.3.2 specification"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }, { readonly method: "GET"; readonly path: "/asyncapi.json"; readonly handler: "asyncApiDocument"; readonly paramNames: []; readonly summary: "AsyncAPI 3.0 specification"; readonly tags: ["System"]; readonly responses: readonly [{ readonly status: 200; readonly description: "AsyncAPI 3.0 specification"; readonly content: readonly [{ readonly mediaType: "application/json"; readonly schema: "object"; }]; }]; readonly access: "public"; }]; /** * Convert an Express-style path to an OpenAPI path template. * `/v1/workflows/:id/signal/:name` → `/v1/workflows/{id}/signal/{name}` */ export declare function toOpenApiPath(path: string): string; /** * Convert an Express-style path to a regex pattern for route matching. * * Each segment is either a literal (with regex metacharacters escaped) or a * parameter placeholder: * - `:step` becomes `(\\d+)` for numeric-only matching (checkpoint routes) * - `:name` becomes `([^/]+)` for any non-slash token * * Escaping the literal segments prevents characters like `.` in paths such as * `/openapi.json` from being treated as wildcards (which would match * `/openapiXjson`). */ export declare function toRegex(path: string): RegExp;