import { type Actor, type PlatformRequestEntry, type PlatformRequestFilter } from '@substrat-run/contracts'; /** * The one SELECT behind every read of a scope's intent journal (#618). * * Three surfaces answer the same question from the same table — `ctx.platformRequests` inside an * operation, the host's `listPlatformRequestHistory` for the control plane, and the Durable * Object's RPC underneath it — and they must not drift on which columns come back or what * "newest" means. Ids are ULIDs, so `ORDER BY id DESC` IS newest-first without a second index. * * The filter is re-parsed here rather than trusted: this builds SQL, and `kind` arrives from an * HTTP query string on one of those paths. Values are bound, never interpolated. */ /** Every column of `_substrat_platform_requests`, in the order the row mappers expect. */ export declare const PLATFORM_REQUEST_COLUMNS = "id, kind, payload, requested_by, impersonation, status, attempts, last_error, last_failure, result, requested_at, settled_at"; export declare function platformRequestHistoryQuery(filter?: PlatformRequestFilter): { sql: string; params: (string | number)[]; }; /** A stored `_substrat_platform_requests` row — snake_case, the JSON columns still text. */ export interface PlatformRequestRawRow { id: string; kind: string; payload: string; requested_by: string; impersonation: string | null; status: string; attempts: number; last_error: string | null; last_failure: string | null; result: string | null; requested_at: string; settled_at: string | null; } /** * What `requestedBy` reads as when the stored actor did not decode. The field is required and * an actor has no empty value, so this is a marker that names itself rather than a plausible * requester: a guessed principal would be the one thing worse than admitting nobody can tell. * The same marker every tolerant spine read uses (#1636), so it is one value, not four. */ export declare const UNDECODED_REQUESTER: Actor; /** * A stored row → the `PlatformRequest` contract shape — TOLERANTLY, and saying so (#1588). * * Every read of the journal returns a LIST, and this decode used to be strict: one row whose * JSON would not parse threw out of the map and took every other intent on the scope with it. * That disabled the drain's own queue, and `listPlatformRequestHistory` too — the read that * exists so a settled intent's failure is legible afterwards (#618), switched off by the row * that failed. Each field is now decoded against its own contract field, and whatever did not * decode is named, by column, in `decodeError`, with the field EMPTY in its place: * * - a JSON column comes back `null`, or {@link UNDECODED_REQUESTER} for the one that cannot be * null. Never the raw text: a raw `payload` would read as a string payload that was never * sent, which is a guess dressed as a fact. * - a nullable scalar (`last_error`, `settled_at`) comes back `null`. * * **Every value this returns satisfies the contract.** A field is only ever replaced by a value * its own schema accepts, so the type is not asserting something the published schema would * refuse — a consumer switching on `status` or passing `id` on as a branded id can trust both. * The price is the REQUIRED scalars (`id`, `kind`, `status`, `attempts`, `requested_at`): they * have no empty value, so a row that breaks one of them cannot be a `PlatformRequest` without * lying. It comes back as the OTHER half of the entry instead (#1637), an * `UndecodablePlatformRequest`: those five columns as stored, as text, and `decodeError` naming * every column it broke. It used to throw, which kept #1588's whole consequence — one row and * the scope's journal was unreadable on all three reads — for exactly these columns. * * A row the kernel wrote decodes whole and carries no `decodeError` at all, so a healthy list * is exactly what it was. This is the READ's half of #1587's rule — strict where work happens, * tolerant where evidence is read; the work half is the drain, which refuses any row carrying * `decodeError` rather than run a handler on it. * * Reachable without a forge: `importDump` replays a dump's rows verbatim, so a dump from * another world, or one edited by hand, is enough. The field-by-field mechanics are * `rowDecoder`'s, shared with the history and denial reads (#1636). */ export declare function platformRequestOf(row: PlatformRequestRawRow): PlatformRequestEntry; //# sourceMappingURL=platform-request-query.d.ts.map