Submit an issue View all issues Source
MIR-1645

Canonicalize deployment records around immutable attempts

In Progress public
phinze phinze Opened Aug 25, 2026 Updated Aug 27, 2026

MIR-1626’s entity-sync research exposed a deeper problem in deployment recordkeeping. The current deployment entity was not designed as a durable domain record, but released clusters already contain deployment history. We need to clean up the model additively before entity sync makes it part of the cloud contract.

Today deployment.status conflates two different facts: whether an attempt succeeded and whether its result is currently serving. A successful deployment starts as active, then a later deployment mutates it to succeeded or rolled_back. Rollback therefore rewrites old history instead of recording a new attempt with rollback intent.

The tracker also has recovery holes. It creates a deployment before acquiring the deployment lock, which can briefly expose a losing attempt as durable history. Activation can succeed before the tracker records success, leaving a live deployment stuck as in_progress. Deprecated writers can bypass some tracker invariants.

The proposed direction is:

  • Define one deployment entity as one attempt to make an app version current.
  • Give each attempt an operation such as build, redeploy, rollback, or config change.
  • Track attempt outcome separately from progress stage.
  • Put current residency on app.active_version and a new app.active_deployment.
  • Record rollback as a new attempt. Earlier successful attempts remain successful.
  • Add typed timestamps, stable initiator identity, safe failure metadata, and curated source metadata.
  • Prevent an attempt from becoming export-visible before it wins admission.
  • Reconcile attempts when activation succeeds but record settlement fails.

Because released clusters already contain the old entity shape, migration must be additive:

  • Keep existing entity IDs and legacy attributes.
  • Add canonical attributes plus a per-entity model version.
  • Read canonical-first and fall back to legacy.
  • Dual-write both shapes for one supported downgrade window.
  • Map legacy active and rolled_back records to canonical succeeded.
  • Do not infer historical rollback or redeploy intent from source_deployment_id.
  • Reconcile abandoned in_progress records using deployment locks and app.active_deployment.
  • Re-run migration after an upgrade because an older binary may strip unknown attributes while rewriting an entity.
  • Reset only unreleased cloud tables and cursors. Never clear runtime deployment history or deployment locks.

Entity sync should export only the canonical allowlist and should not advertise deployment export readiness until the retained deployment migration completes. Raw errors, build logs, actor display data, client-supplied cluster identity, and unfiltered repository URLs must remain local.

Deliverables:

  • A focused RFD defining deployment semantics, invariants, schema, reconciliation, migration, and downgrade behavior.
  • An audit of every deployment writer and transition path.
  • An implementation PR with migration and reconciliation tests.
  • Upgrade, downgrade, re-upgrade, rollback, lost-lock, and activation-settlement test coverage.
  • An update to RFD 109 that treats this model as the deployment example instead of defining it inline.

Related to MIR-1626. The wire protocol and cloud landing-store design remain in MIR-1626/RFD 109.