# Effect control plane The publisher backend uses **Effect 4.0.0-rc.112** and **@distilled.cloud/cloudflare 1.0.0-rc.8**, pinned exactly. The SDK's published peer requirement includes this exact Effect release. Customer Agents, Think, model streaming and scheduled tasks retain their Cloudflare SDK implementations. ## Execution and persistence Application functions return Effects throughout OAuth, sessions and grants, bridge signing and health checks, provider setup, installation commands, artifact verification, deployment and custom domains. Callers compose these programs directly; there are no Promise compatibility implementations alongside them. Configuration errors, authorization failures, resource conflicts and registry failures retain their application error types. Promise execution is confined to native boundaries: - `index.ts` runs the HTTP program with the incoming request's abort signal. - Durable Object RPC methods run storage programs and return serializable values. `registry-result.ts` transports only declared registry codes; `registry-client.ts` and `vault-client.ts` preserve native receivers and derive types from server method contracts before Wrangler adds RPC transport types. - `storage.ts` runs each native transaction callback and rejects it on Effect failure, defect or interruption. This rolls back partial writes while retaining the original local failure channel. Native storage remains authoritative for atomicity, ordering, alarms and persistence. Existing strict Zod metadata parsers remain synchronous, including validation of persisted records. - `workflow-boundary.ts` converts step results to safe durable codes. Each native step attempt rereads authorization and registry state. Cloudflare owns step names, retries, timeouts and durable sleeps. Tokens and Effect runtimes are never persisted in Workflow state. - `cloudflare-sdk.ts` provides request-local OAuth credentials and a bounded fetch transport to Distilled. `Retry.none` disables SDK retries, including retries of accepted mutations whose replies were lost. The native fetch boundary forwards caller cancellation directly and keeps deadlines active through body reads. Artifact caching retains only successfully verified immutable values. It does not share running fibers or rejected Promises across requests. Upload intents still commit after asset staging and before Worker PUT. Container and domain intent records survive ambiguous writes, and recovery observes their outcome before authorizing another mutation. Existing metadata formats and fingerprints remain compatible with installed releases. The old `deployment-effect.ts`, `domain-effect.ts`, `domainCall` and throwing `fail` helper have been removed. Workflow result handling lives in one module. ## Responsibilities The former `deployment-api.ts` has been removed. Provider transport, resource operations and upgrade policy have separate homes: | Module | Responsibility | | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | `cloudflare-account.ts` | Account-scoped SDK execution and bounded requests for unsupported native endpoints | | `worker-api.ts` | Worker settings, versions, assets, uploads and verification | | `container-api.ts` | Container observations, normalization, creation, patching and rollout reconciliation | | `deployment.ts` | Consistent observations across Worker and container resources; upgrade baseline verification | | `model-gateway.ts` | Shared account gateway reconciliation | | `installation-lifecycle.ts`, `domain-lifecycle.ts` | State transitions over validated records, independent of storage | | `installation-registry.ts` | Owner validation, atomic storage, replay and native RPC | | `http-response.ts`, `oauth-authorization.ts`, `installation-access.ts` | HTTP primitives, authorization startup and owner lookup without router dependency cycles | Worker orchestration takes its attempt's client explicitly. No additional Context service or Layer wraps that client. Installation commands and upload bindings use discriminated unions: recovery cannot select a new target release, and a fresh upload cannot also inherit an existing Worker version. Configured Workflow steps receive `InstallationConfig`; behavior does not depend on comparing step-name strings. Persisted step names and record formats remain unchanged. The [structural review](effect-control-plane-review.md) records the findings, refactoring decisions and validation limits. ## Distilled coverage and limits Generated SDK operations supply request, response, failure and service types for: | Integration | SDK operations | | ----------------------- | ---------------------------------------------------------------------------------------------- | | Account authorization | `listAccounts`, with bounded pagination | | AI Gateway | `getAiGateway`, `createAiGateway` | | Worker publication | `getSubdomain`, `getScriptSubdomain`, `createScriptSubdomain` | | Deployment observations | `listScriptDeployments`, `listScriptVersions` | | Asset staging | `createScriptAssetUpload`, `createAssetUpload`, including session JWT and multipart file parts | | Containers | `createContainerApplication`, followed by metadata verification | | Domains | `listZones`, `getZone`, `listRecords`, `listDomains`, `deleteDomain` | **The SDK cannot supply complete types for every integration in this release.** The following narrow Effect adapters remain deliberately explicit: - Cloudflare's authorization-code exchange, UserInfo and revocation endpoints are on `dash.cloudflare.com/oauth2`, outside the generated client-v4 SDK. - `PutScriptMetadata` does not declare the `exports` metadata used for this application's native SQLite Durable Objects. Worker PUT retains its complete multipart metadata, including exports, containers and inherited bindings. - The SDK does not expose the script `/domains/records` attachment operation with its three false override guards. Substituting `putDomain` would change the existing protection against taking over another Worker or DNS record. - Container rollout get/list operations are absent. Container observations and patches retain complete wire configuration because that data participates in persisted fingerprints and must preserve customer configuration. - Worker settings, version resources and content verification need complete wire observations to detect unknown fields and retain existing fingerprint meaning. Although `getScriptScriptAndVersionSetting` includes bindings (unlike the shorter `getScriptSetting` operation), a generated projection does not replace those preservation checks. The SDK protocol can also produce generic HTTP errors absent from an operation's declared failure union: `listAccounts` omits `Forbidden`, and `getAiGateway` omits generic `NotFound`. The adapters recognize the SDK's exported error classes and translate them to application failures; they do not assert exhaustive coverage of those generated unions. There are no SDK patches, generated-schema overrides or casts pretending these unsupported contracts are covered. SDK responses still undergo the application's ownership, shape and size checks; a dependency type is not proof of authorization. Provider bodies and errors are sanitized before HTTP or Workflow history. ## Validation ```sh pnpm typecheck pnpm build:release pnpm build:control-plane:fixture pnpm test:control-plane-effect pnpm test:deployment pnpm test:deployment-network pnpm test:oauth pnpm test:bridge-server pnpm test:ownership pnpm test:orchestrator pnpm test:domains pnpm test:updates pnpm test:installation-status pnpm test:upgrade-state pnpm test:bridge pnpm test:catalog ``` The fixture build is local validation and must not be published as a release. The focused Effect suites cover transaction commit/rollback, interruption, credential isolation, SDK pagination and retry suppression, safe errors, response-body cancellation/deadlines and mutation intent ordering. Native suites exercise OAuth replay and expiry, encryption, owner isolation, upgrades, ambiguous provider replies, process restart, domain reconciliation and browser onboarding. The independent bridge server test exercises native publisher OAuth continuation, single-use exchange, signed provider notifications, health checks and encrypted operation storage. It verifies customer assertions with a local HTTP responder; it does not boot the customer Sandbox. Local validation limits: the existing `test:bridge` browser case still times out at its first customer `/auth/login` navigation, as recorded on the untouched baseline before this migration. The Docker golden-path suite could not run because Docker is not installed in this environment. Neither check is disabled in CI.