/** * FINAL SPEC v1 — the built-app door: `AppsRuntime.build`, plus the resume hook * the decision seam fires into and the seal the build lane lands through. * * The law it exists to keep: no machine is ever spent without the user's * explicit yes. `propose` raises the standing approval card and RETURNS — * nothing here waits on it, because the yes may arrive long after the turn that * asked is gone — and `resume` is the ONLY path from that yes to the builder. * Between the two, the app row says "offered, unanswered" and no box exists. */ import { type AppBundle, type AppId, type ApprovalId, type PendingApproval, type ToolDescriptor } from "@vendoai/core"; import type { BuiltFile } from "../../contract/index.js"; import type { AppsRuntimeContext } from "../runtime/runtime-context.js"; import type { AppsRuntime } from "../runtime/types.js"; /** This ask in words, for the surfaces that render no card. Both halves come * from the shared core tables, which is what makes this the SAME ask the card * shows: `consentAsk` (ui/chrome/build-beat.tsx) reads them too, because * ruling 14 keeps the descriptor's own sentence off the consent ladder. */ export declare const BUILD_CONSENT_ASK: Omit; /** The descriptor the guard parks the ask on. Its `description` is the MODEL's * copy of the same sentence; the words a person reads reach the card through * `VENDO_TOOL_NOTES`, never through here. */ export declare const buildDescriptor: () => ToolDescriptor; export interface SealInput { appId: AppId; files: readonly BuiltFile[]; entry: string; /** The version this reseal started from, recorded on the history entry. */ base?: string; } /** * THE ENFORCER a sealed bundle renders behind, and the reason the frame needs no * trust: `default-src 'none'` is zero network — the bundle was sealed with * everything it needs, so it has nothing to fetch and nowhere to phone home to. * The two `'unsafe-inline'`s are what let the document carry its own script and * styles at all, which is the point: nothing is loaded, so nothing can be * injected from outside. * * `font-src data:` is `img-src`'s trade, made twice for the same reason: brand * fonts are injected AT RENDER as `data:` faces (`sendFrameTheme`), and a data * URI is inline — it costs no request, so the zero-network guarantee is * untouched. A scheme or an origin here would hand that guarantee back. * * It is a HEADER and never a `` tag, because `frame-ancestors` — the half * that says only the host's own page may frame this — is ignored in meta. */ export declare const BUNDLE_CSP: string; export declare const BUNDLE_HEADERS: Readonly>; /** * The frame's whole document: the sealed entry INLINE, and nothing else to * fetch. Brand tokens and fonts are not in here — they arrive by postMessage at * render (`sendFrameTheme`), so one seal follows the host's palette instead of * pinning the palette it was built under. */ export declare function bundleDocument(entry: Uint8Array): Uint8Array; /** The public door (`AppsRuntime.build`) plus the hooks only the runtime's * own seams reach: the decision subscriber's, the build lane's, and the wire's. */ export type BuildDoor = AppsRuntime["build"] & Pick & { /** THE resume hook: what `onApprovalDecision` fires into, and the only caller * of the builder there is. */ resume(approvalId: ApprovalId, approved: boolean): Promise; /** One build's output frozen onto the app: content-addressed blobs, the row's * compare-and-swap, and a history version. Every seal IS a version. */ seal(input: SealInput): Promise; }; export declare const createBuildDoor: (deps: Pick) => BuildDoor; //# sourceMappingURL=build-door.d.ts.map