Status: local release runbook. Completing these checks does not itself push, deploy Forge, attach a domain, or change production traffic.
deploy_projects owns each project's root, enabled state, and environments.Work is partitioned by Forge project for builds and by provider Worker for publication, promotion, retirement, and domain reconciliation. A failure in one project must not move another project's pointer or roll it back.
.forge/config.json, validate the exact-SHA file
against the repository configuration contract.
Confirm the reviewed defaults, permanent project slugs, roots, binding
match modes, and plan digest.forgeBuild.ts.workspace:* dependencies, but not
unrelated sibling applications.
For pnpm v9, confirm the frozen lockfile importer index was accepted; an
unsupported importer shape must take the conservative full-tree discovery
fallback instead of omitting a workspace.Never place Git clone credentials, Cloudflare credentials, secret values, or DNS authority in the build sandbox.
@opennextjs/cloudflare declaration and
an exact resolution in a supported npm, pnpm, or Bun root lockfile.
For the vetted 1.19.11 target, require Next
>=15.5.18 <16 || >=16.2.6 <17; do not publish a Next 13 project.npx, dlx, or an implicit latest..open-next compiler
input. Require worker.js, assets, and cache; permit only contained pnpm
symlinks and reject special files, escapes, or compiler-input overflow.For ISR, the trusted helper may inherit only the exact R2 cache binding and an ephemeral token. It must stay at zero percent, upload bounded digest-verified objects, survive retries through its durable operation ledger, and be removed before the application candidate is published.
GET /api/repos/:owner/:repo/sites/migration/assets?sha=<sha> or the Sites
adoption card. This is read-only and does not execute repository code.public/** and greater-than-5-MiB file defaults.uploaded: false, use the standard Forge LFS
Batch/basic HTTP API to upload and verify the exact bytes. A local git-lfs
binary is not required. Inspect again before apply.preview_behavior: "suppressed". Confirm the production branch and all
deployment pointers are unchanged.For an enabled connected project whose project and production-environment
publication modes are both auto, Forge reconciles the newest ready release
for the current production ref through the same provider-activation operation
used by an explicit promotion. The activation must still prove the exact head
SHA, ready artifact, approved target, binding generation, Forge environment
generation, active deployment, and frozen provider base. A failed build or a
stale candidate never reaches this reconciler. Push releases also freeze the
matching Action run IDs and wait until every recorded run has completed
successfully. A scheduled pass repairs an interrupted reconciliation
idempotently.
An ordinary Action for a repository with an approved connected target may run
tests, builds, and read-only verification, but it must not activate a plain
Worker version with wrangler deploy. The runner rejects that production
mutation because it would bypass the release-scoped private bindings and the
Forge deployment ledger. Remove the raw deploy step from such a workflow and
let Automatic publication activate the connected release, or use Forge's
explicit promotion operation when the project is configured for manual
publication.
Treat these as separate evidence: the repository push, its exact-SHA Action, the ready connected artifact, the succeeded provider activation and receipt, the Forge production pointer, and the live hostname. No one record implies the others.
Repository builds receive no DNS authority. An authenticated project administrator records desired state, then uses a separate explicit apply action.
A repository may propose this desired state in .forge/config.json. Treat it
as exact-SHA, statically validated intent only. Inspect first, review the plan
and digests, then explicitly import. New projects remain disabled. Existing
projects preserve their enabled or disabled state while reviewed roots,
production branches, and publication modes are updated. A missing or disabled
target stays unresolved; an already-approved target that does not allow the
declared zone blocks import. Import never applies provider state, and an
omitted entry never means detach. If an independent project partially imports
before a later failure, repair the contract, inspect again, and approve the new
plan digest before retrying.
Before apply, prove the hostname is in an approved owned zone, has no competing Forge claim or conflicting CNAME, and the path route has unambiguous precedence. Record the desired generation before calling Cloudflare. Persist the provider receipt, certificate/DNS observations, and any retryable error.
A path_route is one logical wildcard-free path with one of two match modes.
exact_and_descendants is the default and preserves lexical siblings: Forge
reconciles the exact path plus its / descendants. reserved_prefix is an
explicit namespace reservation: Forge uses a broad provider pattern such as
host/archive*, which covers the query-bearing root and descendants but also
captures siblings such as /archive-old. Approve it only when one project
intentionally owns that whole lexical prefix. Apply and detach inspect every
expected provider pattern and fail closed on unexpected overlaps or ownership
drift.
A main Worker Custom Domain and more-specific archive path bindings may share
one hostname. Cloudflare evaluates the matching Worker Route before the Custom
Domain, so Forge does not model the main Worker as a /* path route.
One Cloudflare matching limit remains an explicit application gate. Archive
prefixes do not capture Next Pages Router data URLs such as
/_next/data/<build-id>/archive.json; reviewed document navigation can avoid
those client data requests. The explicit reserved_prefix mode solves the
query-bearing archive root by reserving the broader lexical prefix; its sibling
capture is intentional and must be reviewed before apply. Cloudflare does not
support arbitrary infix Worker Route wildcards.
Detach is reversible desired state. Keep the claim until Cloudflare proves the domain or route is detached. Never delete an active domain without a confirmed replacement or an explicit detach.
Retention protects the active deployment and the configured rollback candidates. Provider-version cleanup is serialized with promotion, rechecks current deployment membership, and never deletes a 100% production version. An interrupted or provider-rejected cleanup retains its receipt and returns to retryable reconciliation.
Report these as separate facts: