import type { DeployVerticalFn, FetchVerticalModulesFn } from './deploy.js'; /** * Bound a (potentially large, untrusted) upstream error body before it rides inside a * thrown Error and a JSON response — but mark the cut EXPLICITLY. The old bare * `.slice(0, 400)` ended mid-token (`…eka/set-budg`) with no sign anything was omitted, * so a reader could not tell a real operation name from a severed string, nor that the * rest of the list existed (#307). A generous cap keeps an unbounded body from flooding * the log while the marker states exactly how much was dropped. */ export declare function clip(body: string, max?: number): string; /** * A `DeployVerticalFn` that uploads a bundle into a Workers-for-Platforms **dispatch * namespace** (orchestration.md §5.2). It is pure web-standard `fetch` + `FormData` — * no Cloudflare SDK, no node built-ins — so it runs unchanged in a Worker (the control * plane holds the token as a secret) or in node (the dev server, tests against a real * namespace). The multipart shape is exactly what `wrangler deploy` sends and what the * K-28 spike verified. */ export interface WfpUploaderOptions { accountId: string; namespace: string; /** A Cloudflare API token with Workers Scripts / dispatch write. Platform-held. */ apiToken: string; /** * Platform-owned secrets injected as `secret_text` bindings on every pushed script — * the ambient credentials a vertical needs to VERIFY inbound platform/router calls * (`PLATFORM_SECRET` for `/internal/provision`, K-31; `ROUTER_SECRET` for the routed * node, K-27). The vertical does not declare these (they'd fail the §4 sandbox check * with no value to give); the platform provides them at deploy from its own env. * Names with an undefined/empty value are skipped. */ injectSecrets?: Record; /** * Bind Workers AI (`env.AI`) on every pushed script (#1054). * * Deliberately a BINDING and not a credential. The alternative was injecting a Workers * AI token as one more `secret_text`, and a pushed vertical can read those: the push * gate checks DECLARED bindings, never the code, so R2's ban on `cloudflare:workers` * — what stops module code reaching ambient `env` — is not enforced here (#862). A * spending credential under that hole is not something to ship; a binding leaves * nothing to read, and Workers AI bills the account owning the script, which is ours. * * Verified on TEST rather than inferred (D-58's discipline): a throwaway * dispatch-namespace script accepted `{type:'ai',name:'AI'}`, read back as * `{name:'AI',project:'',type:'ai'}`, and ran inference through it — with and * without a gateway id, reporting real prompt/completion token counts. * * The honest limit: this is a CAPABILITY the vertical holds, so a vertical can call * `env.AI.run()` on our account without passing our gateway id, unattributed. Bounded * to Workers AI and cheaper to bound further (gateway spend limits); the durable fix is * running inference platform-side, which is what BYOK needs anyway. */ bindAi?: boolean; /** * Head sampling rate (0–1) for Workers **automatic tracing** on pushed scripts (#858). * Absent ⇒ no `traces` block, which is what every push has sent until now. * * Separate from `observability.enabled` because Cloudflare says it is: *"While automatic * tracing is in early beta, this setting will not enable tracing by default, and will only * enable logs."* So the `enabled: true` below has been buying logs and nothing else, and a * `traces` block is the only thing that turns spans on. * * A **rate rather than a boolean** on purpose. Tracing instruments every I/O operation, each * span is one observability event sharing quota with Workers Logs, and beta pricing ends * 2026-10-01 — so the fleet-wide question was never "on or off" but "how much", and a dial * lets TEST run at 1 while prod stays dark or samples. Undefined and 0 are NOT the same: * undefined omits the block, 0 declares tracing and samples none of it. * * Why this is worth the option at all: the DO-originated subrequests D-46 documents as * unenforceable are also, today, unobservable — and `durable_object_subrequest` spans are * the first mechanism that sees them. */ traceSampling?: number; } export declare function createWfpUploader(opts: WfpUploaderOptions): DeployVerticalFn; /** * One D1 binding to guarantee on a dispatch script — the shape `PatchScriptBindingsFn` * ensures and the serving upload injects (per-tenant stores, #301). */ export interface D1BindingSpec { name: string; /** The D1 database id (the tenant-store ledger's `ref`). */ id: string; } /** * One R2 binding to guarantee on a dispatch script (per-tenant blob stores, #473) — the * exact twin of {@link D1BindingSpec}, differing only in the Cloudflare binding shape a * bucket takes (`bucket_name`, not `id`). */ export interface R2BindingSpec { name: string; /** The R2 bucket name (the blob-store ledger's `ref`). */ bucketName: string; } /** A binding the patcher guarantees on a serving script — a per-tenant store (#301) or * blob store (#473). Discriminated so one PATCH carries both kinds. */ export type ScriptBindingSpec = ({ type: 'd1'; } & D1BindingSpec) | ({ type: 'r2_bucket'; } & R2BindingSpec); /** * Ensure a set of per-tenant bindings exists on a dispatch-namespace script WITHOUT * redeploying it (#301/#473): attach a freshly-minted store to the vertical's serving * script the moment it is provisioned, between full uploads. Resolves without touching * Cloudflare when every wanted binding is already present. */ export type PatchScriptBindingsFn = (scriptName: string, ensure: ScriptBindingSpec[]) => Promise; /** * A `PatchScriptBindingsFn` over the namespace's script-settings endpoint: read the * current bindings, add the missing ones, PATCH the set back. Additive on purpose — it * never removes a binding (reap-time cleanup is the ledger's job, a separate step), and * secrets are never round-tripped: the GET cannot return their values, so they ride * `keep_bindings` exactly as an in-place upload's do (#286). */ export declare function createWfpBindingsPatcher(opts: Pick): PatchScriptBindingsFn; /** * A `FetchVerticalModulesFn` over the namespace's script-content endpoint. The archive * script (one per pushed version) is the platform's bundle store — promote and backout * read the built modules back from it rather than requiring anyone to retain bytes. * * Cloudflare answers with `multipart/form-data` for a multi-module script and with the * bare module body (entrypoint named in `cf-entrypoint`) for a single-module one; both * shapes are handled with web-standard parsing only. In the multipart shape, a module * part need not carry `filename=` — the response is Cloudflare's format, not an echo of * the uploader's — so a part that parses as a string (not a File) is still a module. */ export declare function createWfpModulesFetcher(opts: Pick): FetchVerticalModulesFn; //# sourceMappingURL=wfp.d.ts.map