/** * approvals.raise, a surface RAISING an ask into the daemon's broker. * * ── The gap this closes ──────────────────────────────────────────────────── * * `approvals.list/claim/approve/deny/cancel` have existed for a long time, so * every surface could SEE and DECIDE an ask. None of them could create one: the * only way into the broker was `ApprovalBroker.requestApproval`, an in-process * method call. A surface that is not in the daemon's process, a client whose * runtime lives on another machine, or simply another process on this one, * therefore had no way to route a permission ask through the daemon at all. It * kept its own broker, prompted at its own terminal, and the asks it raised * were invisible to every other surface and to the daemon's own attention * machinery (the web-push fan-out, the fleet blocked-on-user signal). * * ── Why it does not block ────────────────────────────────────────────────── * * The verb returns the PENDING record and returns it immediately. It does not * hold the call open until someone answers, for two reasons: an HTTP request * parked across a person's attention span is a request that dies to any idle * timeout between here and there (and over the relay there are several), and * the decision has a better channel already, `control.approval_update` on the * SSE stream carries every transition of this record the moment the broker * records it. So the shape is: raise, then watch the id you were handed. * * `waitMs` is offered for the caller that genuinely wants one round trip (a * script, a short-lived CLI). It is CLAMPED, and a wait that runs out is not an * error: the response comes back with the record still pending and * `decided: false`, which is the truth. Nothing here ever reports a decision * that was not made. * * ── Who owns the answer ──────────────────────────────────────────────────── * * The daemon does. A raised ask becomes a record in the daemon's store, several * surfaces may claim and answer it, and what a surface renders afterwards is * what the record says, not what it locally believes it asked for. That is the * same parity contract the web UI already documents for the decide verbs, and * raising through this verb is what extends it to the ask itself. */ import type { GatewayMethodCatalog } from '../method-catalog.js'; import type { GatewayMethodHandler, GatewayMethodInvocation } from '../method-catalog-shared.js'; import type { PermissionPromptRequest } from '../../permissions/prompt.js'; import type { RequestSharedApprovalInput, SharedApprovalRecord } from '../approval-broker.js'; import type { RaisedApproval } from '../approval-broker-raise.js'; /** The broker surface this verb needs, nothing but raising and reading back. */ export interface ApprovalRaiseService { raiseApproval(input: RequestSharedApprovalInput): Promise; getApproval(approvalId: string): SharedApprovalRecord | null; } /** * Longest inline wait a caller may ask for, in ms. * * 60s is chosen against what is on the other side of the call rather than * against what a person takes to decide: an idle proxy, a tunnel, or a browser * fetch will drop a parked request well before a slow answer arrives, and a * dropped request looks like a failure rather than like "still waiting". A * caller that needs longer is the caller that should be on the event stream. */ export declare const APPROVAL_RAISE_MAX_WAIT_MS = 60000; /** Longest expiry a raised ask may carry, in ms. Twelve hours. */ export declare const APPROVAL_RAISE_MAX_TIMEOUT_MS: number; /** * Validate the ask itself. * * A raised ask is rendered by every surface and stored durably, so a malformed * one is refused at the door rather than persisted and drawn as a blank prompt. * The required set is exactly what the broker's own store validator demands of * a restored record, an ask that could not be reloaded must not be creatable. */ export declare function readApprovalRaiseRequest(raw: unknown): PermissionPromptRequest; /** * Who raised this, recorded on the record's metadata. * * A raised ask that says nothing about where it came from is an ask an operator * cannot audit: several surfaces can now create records in one store, and "the * TUI asked" versus "a token asked" is exactly the distinction that matters * when reviewing what was approved. The invocation context already carries the * authenticated principal, so the attribution is the daemon's own observation * rather than a claim the caller makes about itself. */ export declare function buildRaiseMetadata(invocation: GatewayMethodInvocation, supplied: unknown): Record; export declare function createApprovalRaiseHandler(broker: ApprovalRaiseService): GatewayMethodHandler; /** Attach the approvals.raise handler to its descriptor. Missing descriptor is a silent no-op. */ export declare function registerApprovalRaiseGatewayMethods(catalog: GatewayMethodCatalog, broker: ApprovalRaiseService): void; //# sourceMappingURL=approvals-raise.d.ts.map