Pre-release installation updates #
The publisher ships only the latest immutable customer bundle and updates through the native InstallationWorkflow. Workers, Durable Objects and Sandbox resources stay in each customer's Cloudflare account, billed to that customer. Automatic updates are best-effort within the supported pre-release contract, not a promise to migrate every historical or partially deployed state.
The supported v0.1 edge keeps application SQLite schema 1, the personal Agent identity, PersonalAgent/Sandbox class exports and SQLite storage, and Conversation facets unchanged. Configuration schema, application schema and SDK-owned schemas are separate contracts. There is no unnecessary data rewrite, export/import, custom scheduler or rollback service. Future schema changes require deliberate customer-owned ordered atomic migrations and new compatibility validation; they are rejected by this version.
Packaging and selection #
Release 0.1.0-dev.7 has a new immutable identity rather than reusing the already-published dev.6. Its explicit compatibility list includes the original dev.6 artifact digest 4c0e2ed811f0f254890af50c92c73bd6ea9e224ae77cbca066e285f29ddf92ca. Before deploying it, review the publisher's retained FLAREBOT_CONTROL_PLANE OAuth capability attestation and set oauthCapabilities.artifactVersion to 0.1.0-dev.7; a package version bump does not update deployed configuration.
After pnpm build:release, run pnpm build:control-plane. Retained inputs (FLAREBOT_RETAINED_RELEASES or --retain) are rejected, not silently ignored. Keep original archives outside the publisher for operator emergency recovery, never overwrite them or regenerate them from old Git source. The current bundle's manifest and every inventory file are verified before use; dirty production input and size excess fail closed. Generated opaque Data modules remain outside the browser graph.
On an authenticated owner HTML visit, a production customer Worker checks the publisher's minimal public latest-release identity. An outdated instance redirects to the publisher's update page. That page independently authenticates the owner, checks the installation and compatibility, revalidates account authorization, and starts one exact-target upgrade without an approval prompt. It shows progress and returns to the instance after success. Unauthenticated requests, APIs, health checks and local development do not trigger updates. If the publisher is unreachable, the installed application remains available.
Workers deployed before the visit trigger was introduced need a one-time update from Installation settings. Updating the publisher cannot inject this behavior into already-deployed customer code. Expired grants require reconnection. Failed or incompatible installations stop with manual recovery guidance, and ambiguous saved requests are not automatically resubmitted or replaced with a newer target.
Authenticated POST /api/installations/:id/upgrade accepts URL-encoded requestId and target (the exact latest ReleaseIdentity serialized as JSON). The browser freezes its nonsecret request intent. The server checks the exact version/revision/digest, verifies owner and selected account again, and reserves one native operation. Concurrent starts cannot overlap. Replay cannot move a request to a newer release or installation. If a pinned in-flight target has been retired, retry/recovery fails with artifact_unavailable before customer writes instead of silently retargeting it.
Deployment safety and recovery #
New installation uploads persist the exact installation configuration fingerprint before PUT. Upgrade preflight checks the installed release's explicit compatibility edge, deployed release/operation markers, configuration fingerprint, supported runtime/exports, stable namespace IDs, endpoint and owned Containers application. It hashes the observed deployed modules and pins that hash for subsequent race/drift checks; it does not certify historical source against an archive or detect edits made before preflight. The target still receives exact-byte validation. A private baseline stores only identities, deployment identifiers and canonical hashes. Customer settings, code bytes, secrets and Container environment variables stay transient inside protected callbacks.
For a retired or incompatible target, an operator must inspect the installation and remote resources, then arrange an explicitly authorized repair using the external archive or a reviewed current deployment. Do not automatically delete/recreate Durable Objects, reset storage, restart an ambiguous upload, or mark an unverified deployment ready. Reinstallation involving data loss requires separate owner approval. This limitation is intentional during pre-release.
The uploader uses native bindings_inherit=strict with version_id: "latest", the value accepted by the live script PUT endpoint. During observation and immediately before PUT, the newest uploaded version must equal the checked active version; a newer undeployed upload blocks inheritance too. Only the installation release marker and Assets binding are replaced. All other bindings—including the session secret, customer variables, KV and service bindings—are inherited. No new bootstrap secret is generated for upgrades. The existing bridge public pin remains in the installation configuration. Unsupported changed Worker settings fail before asset staging; supported limits, placement, observability, tail consumers, Logpush, usage model, tags and writable message/tag annotations are preserved through native upload metadata. Cloudflare's read-only workers/triggered_by annotation is excluded from that preservation comparison. The observed runtime asset-routing defaults and container-to-Sandbox mapping must match Flarebot's upload; changed values or unrecognized fields still stop the upgrade.
The Workflow observes the active deployment before and after verification and immediately before upload. It persists upload intent before PUT and adopts exact desired bytes after a lost response, checking the preserved binding/configuration fingerprint. An ambiguous still-old deployment requires explicit owner recovery before another upload. Missing or conflicting resources are never recreated as an upgrade. Containers keep application identity and namespace, preserve unrelated configuration including environment arrays, persist update/rollout intent and rollout ID, paginate lookup and wait for completion. Native health runs only after reconciliation.
A failed attempt retains the last verified installed version and installation time. Direct Worker PUT can already have activated the attempted version before a later health failure; the UI explains this and keeps the stable owner login link available. Recovery is forward repair, not automatic restoration of older code. Active recovery stops the native execution, then reconciles remote effects; it cannot retract an already-sent API request.
Installations made by the unreleased predecessor without an immutable configuration fingerprint cannot be upgraded automatically. They fail with resource conflict rather than treating observed customer edits or today's publisher bridge key as the original configuration. Bridge key rotation is a separate explicit compatibility operation. API metadata does not reveal secret values, so it cannot prove that an account administrator never rotated a secret. Cloudflare script PUT offers no documented transactional compare-and-swap across independent account administrators. Checking active and newest-uploaded version IDs reduces races, but another administrator can still upload between the final check and PUT, changing what latest inherits. Avoid concurrent external uploads during an upgrade; unreadable secret changes cannot be detected by the post-upload metadata comparison.
Validation #
pnpm test:orchestrator exercises native Workflow/registry/vault against a fixed provider API fixture, including two distinct checksummed releases, guarded strict inheritance, preserved customer bindings/config/Container arrays, drift rejection, exact target replay and safe failures. pnpm test:upgrade-state separately compiles two distinct fixture Worker bundles and assets, stops and restarts native workerd on the same persisted SQLite/class identities, and checks real Conversation messages/facets, instructions, memory, encrypted BYOK, native schedules/history, existing owner cookie and fresh production bridge login. These tests do not claim a live account upload or live Containers rollout certification.
Native contracts: Worker upload and strict binding inheritance, declarative SQLite class exports, Containers rollout models.