Migration window
The economy version of an entangled state is sealed. Once your state machine's
domain_economy_config row is created, the keep ratio, spend split,
and mint rate are frozen for the lifetime of that entangled state. To upgrade
those parameters — or to move from the legacy v1_handpicked formulas
to the math-derived v2_math formulas — you open a migration window.
Updated 2026-05-18 to match the AS.F.MATH.M8 release.
1. Why a window exists
Economy parameters change wallet outcomes. If we let an operator flip keep-ratio mid-day, holders would see retroactive differences in the amount of ZEQ minted, retained, or charged for the same action. The window is the formal answer to that:
- The window names exactly which target the entangled state is migrating to.
- Both versions are visible side-by-side (see
econ_v1_previewandecon_v2_previewon the per-Zeqondnetwork_snapshotsrow). - The cutover is a single recorded event, written to the audit entangled state with the operator's ZID, the source/target versions, and the Zeqond at which the swap took effect.
- Once cut over, the change is irreversible in code. Reverting would require opening a new window and a second audit trail.
2. The three states
A migration window is a small state machine of its own:
inactive ──open──▶ open ──cutover──▶ closed
└──cancel───▶ closed
| State | Meaning |
|---|---|
inactive | No window is open. The entangled state runs on whatever version is in domain_economy_config.econ_version. This is the resting state. |
open | The entangled state owner has opened a window. Both versions are computed every Zeqond and surfaced in the transparency oracle. Wallets still settle on the CURRENT version. The owner can either cut over or cancel. |
closed | The window has terminated. Either via cutover (the new version is now authoritative — wallets settle on it from the next Zeqond) or via cancel (no change, returns to inactive). |
An entangled state can only have one window open at a time. Opening a second window on an already-open entangled state is a no-op; the existing window is reused.
3. Lifecycle (federated path)
A federated entangled state migrating v1_handpicked → v2_math:
Open. Owner calls POST /api/chain/<machine>/economy/migration/open
with target_version: "v2_math". Server writes
migration_window_state = 'open', records the requesting ZID,
captures the source version, and emits a migration.opened audit row.
The transparency oracle starts populating econ_v2_preview alongside
econ_v1_preview.
Observe. Both projections are written every Zeqond. The owner can compare:
- daily mint rates (foundation flat-mint vs. math-derived per-machine drip)
- per-tier daily Promo Credits
- spend split outcomes at N=1, 100, 1k, 10k
- the foundation's incoming flow
Cutover. When the owner is satisfied,
POST /api/chain/<machine>/economy/migration/cutover flips
domain_economy_config.econ_version to v2_math, writes
migration_window_state = 'closed', and emits a migration.cutover
audit row stamped with the cutover Zeqond. From the next Zeqond
onward, tallyAutoMint, chargeForCompute, and the keep-ratio
ticker all read v2_math formulas.
Cancel. At any time before cutover, the owner can
POST .../migration/cancel. The window closes, the entangled state returns
to its source version, and the v2 preview stops being written.
4. Auto-cutover (zeq.dev path)
For the framework's own foundation chain (zeq.dev), the cutover
was scheduled rather than manual. The migration window opened on
2026-05-18, ran for a configurable observation period
(auto_cutover_at_zeqond on the window row), and the daemon flipped
to v2 at the scheduled tick. The flip writes the same
migration.cutover audit row, but with triggered_by = 'scheduler'
instead of a user ZID.
Operators of federated/sovereign chains can use the auto-cutover
field too, by setting auto_cutover_at_zeqond at open time. Leaving
it null means manual cutover only.
5. What can't change after cutover
The cutover writes the new version into domain_economy_config but
does not edit other rows in that table. The split percentages,
keep ratios, and mint rate are still sealed by their own
locked-once trigger (see ZEQ economy §5).
A v1→v2 migration changes the formula family; it does not let
you re-tune the parameters of the new family.
If you need to re-tune parameters under v2, the path is:
- Open a new migration window with
target_version: "v2_math"(same version, different proposed parameters). - The server requires
target_paramsto be supplied; the preview is computed using those new parameters. - Cutover applies the new parameter set in a single atomic write.
6. Forensic guarantees
Every transition writes a row to the audit entangled state:
| Event | Captured fields |
|---|---|
migration.opened | source_version, target_version, requested_by_zid, auto_cutover_at_zeqond |
migration.cutover | source_version, target_version, triggered_by, cutover_at_zeqond, network_snapshot_at_cutover |
migration.cancelled | source_version, cancelled_by_zid, reason |
The cutover row also pins a hash of the
network_snapshots row at that Zeqond, so the entire wallet state
of the entangled state at the moment of the swap is content-addressable and
verifiable later.
7. Public surfaces
While a window is open, three places surface it:
/transparency/— showsmigration_window_state: openin the banner, with both v1 and v2 preview cards rendered side-by-side./state/admin/(chain-owner) — the Economy tab shows the open window and exposes theCutover/Cancelbuttons./api/chain/<machine>/state— the public read-only state response carriesmigration_windowas a structured field.
After cutover, only the audit row remains accessible (via the entangled state explorer); the window row itself is closed and read-only.
Bottom line. A migration window is the only way to change a
chain's economy version, and the only way to upgrade legacy v1
chains to math-derived v2. It is auditable end-to-end, reversible
only before cutover, and emits a single canonical row at the moment
of the swap. The framework's own entangled state on zeq.dev migrated this
way on 2026-05-18.