# Trusted merge and production release

This is the normative normal Forge infrastructure-release contract. Its
machine-readable form is
[`../../config/forge-release-system.json`](../../config/forge-release-system.json).
It does not govern ordinary Forge Deploy application activation or an
authorized direct Wrangler repair of Forge's own impaired release machinery;
those boundaries are defined in
[`../operations/production-deployment.md`](../operations/production-deployment.md).

## Preview, merge, build, publish

Pull requests are serialized through one dedicated `fpv-cell-*` platform stack
with preview-only D1, R2, dispatch, analytics, and container resources. A D1
owner row grants exactly one active validation a monotonic cell generation.
Candidate D1 migrations run before version upload; provider versions,
deployments, bindings, and probe receipts remain bound to the exact validation
SHA and cell generation even though the Worker names are stable. Interrupted
attempts may perform one bounded readback of their exact provider identity;
they never blindly republish or resume a resource rollout.

The trusted base probe contract always requires `/health` and
`/health/dependencies` to return `{ "ok": true }` at status 200 and `/register`
to contain the invite-code marker. Repository configuration may add probes but
cannot remove or weaken those requirements. Runner Dockerfile, Wrangler
container configuration, and toolchain changes build inside the rootless-DinD
preview runner. The exact image digest is attached to a private attempt-derived
preview host/application, read back from Cloudflare, and selected by the stable
preview runner Worker binding before deep health. A partial or mismatching
existing host fails that attempt and is never repaired in place; a new attempt
derives a new write-once artifact set.

`RepoLock` serializes merges. Its final D1 transaction rechecks current preview
configuration and every immutable validation/probe fact, appends one
`forge_main_generations` row, advances the target ref with compare-and-swap, and
marks the pull request and queue entry merged. This transaction never queries
Cloudflare production readiness.

The resulting main push invokes `Production Builder`. The builder materializes
only the exact merged main SHA, installs dependencies, compiles, and uploads a
zero-traffic immutable version for each project affected by that direct main
update. Projects build independently. The signed upload broker is stateless and
may persist build evidence, but cannot change traffic.

For `runner`, the complete build includes a digest-pinned image and one private
write-once host/application derived from SHA, main generation, workflow run,
and workflow attempt. The stable runner version has no local
container application; its external `Sandbox` binding selects that host. The
builder may create and read these unreferenced artifacts, but only
ProductionDeployer may publish or restore the stable runner deployment. There
is no host/application lane, current pointer, repair loop, or D1 authority.

Each ready row contains project/environment, full source SHA, main generation,
workflow run and attempt, exact-main release manifest, provider script/version
and tag, manifest/artifact/content/binding/upload-receipt digests, state, and
timestamps. A failed sibling does not discard ready versions.

## Per-project lifecycle

```text
requested -> building -> ready -> publishing -> published
                 |          |          |
                 +----------+----------+-> failed
                            +------------> superseded
```

Retries create a new immutable attempt. Ready versions are never silently
deleted. The publication lane always selects the newest eligible ready main
generation, not the build that finishes last. Once generation N publishes, any
older requested or ready row in that lane becomes explicitly superseded.

Each Worker is an independent deployment unit. There is no global platform
candidate, component operation, dependency wave, cumulative production
baseline, or controller ceremony. Services that cannot be versioned
independently must be combined into one Worker.

## The ProductionDeployer boundary

One Durable Object per environment/project stores only its monotonic fence,
published-generation floor, and exact in-flight deployment ID. It does not
store source, manifests, provider credentials, health, build phases, or an
active-version pointer.

For the selected ready row, the deployer:

1. verifies the stored exact-main manifest and immutable Cloudflare version;
2. reads and records the exact current 100% deployment/version immediately
   before mutation;
3. rechecks expected current under the exclusive stable-deployment writer,
   creates a target-only 100% deployment, and reads it back exactly;
4. verifies exhaustive bindings plus only manifest-declared generic identity,
   `/health`, and `/health/dependencies` observations;
5. atomically marks the row terminal and appends its receipt; or
6. after a post-traffic failure, restores the recorded prior version only while
   the failed deployment remains current, verifies the restore, and appends the
   truthful rollback receipt.

Cloudflare's active deployment is runtime truth. D1 is a deployment/read model,
not a competing authority. Cloudflare has no conditional deployment-create
API, so this is an expected-current guard—not provider CAS—and deployment
credentials are exclusive to this path. Exact pre-read and post-readback checks
are mandatory. Ambiguity retains the same in-flight
identity for reconciliation; it never permits a different ready row to run.

## Data and operator safety

The release schema is additive through the rollback window. Accounts,
credentials, sessions, repositories, projects, releases, publications, and
content are not rewritten or deleted. A schema contraction requires recovery
evidence plus compatibility with both live and rollback binaries.

An expedited invocation of this normal lane may attach operator and reason
metadata to the newest eligible ready row; it still enforces ordering,
expected-current checks, evidence, health, receipts, rollback, and the
ten-minute stop-loss. Do not confuse that invocation mode with the independent
operator-repair lane. When this lane or one of its dependencies is unavailable,
degraded, or implicated in an incident, an authorized Forge operator may repair
exactly one infrastructure component through direct Wrangler using recorded
current state, rollback, focused checks, binding verification, health, and the
original reproduction. Forge metadata reconciliation follows the repair and
does not block it. Direct provider deployment remains forbidden as a silent
substitute for a Forge Deploy application release.
