Skip to content

Upgrading

LatchGate follows semantic versioning. This page documents breaking changes, migration steps, and data-format changes across versions.

For any minor or patch release, the procedure is:

  1. Back up the ledger and signing keys before upgrading:

    Terminal window
    # Back up the ledger database before upgrading
    sqlite3 "$(latchgate config get ledger_db_path)" ".backup /backups/pre-upgrade-$(date +%Y%m%d).db"
    cp .latchgate/operators/keys/receipt.key /backups/
    cp .latchgate/operators/keys/grant.key /backups/
    cp .latchgate/operators/keys/receipt.jwks /backups/
  2. Drain the gate so in-flight executions complete:

    Terminal window
    # Via the admin UDS (production) — requires operator auth headers.
    # The SDKs and TUI construct DPoP proofs automatically; for curl,
    # use the admin socket with operator key + DPoP proof from your
    # integration tooling, or use the TUI:
    latchgate tui # Dashboard → Drain
  3. Wait for drain to complete (in_flight_executions: 0):

    Terminal window
    # Poll the admin status endpoint (the CLI `status` command does not
    # expose in_flight_executions — use the admin API directly):
    curl --unix-socket /run/latchgate/gate-admin.sock \
    http://localhost/v1/admin/status | jq '.in_flight_executions'
  4. Stop the gate (SIGTERM).

  5. Upgrade the binary (brew upgrade latchgate, pull new Docker image, or replace binary).

  6. Verify configuration with the new binary:

    Terminal window
    latchgate config validate
    latchgate doctor
  7. Start the gate with the new version.

  8. Verify via smoke test:

    Terminal window
    curl http://localhost:3000/healthz
    # run a low-risk action via SDK to confirm end-to-end flow

For major version upgrades, consult the release notes for that version in addition to the general procedure.

Gate versionSDK compatibilityLedger formatGrant formatReceipt format
0.1.xSDK 0.1.xv1v1v1

Each row documents the schema version for durable artifacts. A newer gate can read older formats, but older gates cannot read newer formats without downgrading the data.

No releases yet — placeholder for the first breaking change.

When 0.2.0 is released, this section will document:

  • Any configuration fields that were renamed, moved, or removed
  • Any ledger schema migrations (handled automatically by latchgate serve on first start; backups required)
  • Any API response field changes (non-breaking changes don’t require a major bump)
  • Any grant or receipt format changes (historical verification still works via signing_key_id and JWKS)
  • SDK compatibility notes (new gate versions maintain compatibility with one previous SDK major version)

SQLite schema changes are applied automatically by latchgate serve on startup. The startup log shows:

INFO ledger schema migration v1 => v2 applied in 142 ms

If a migration fails (e.g., disk full, corrupted database), the gate refuses to start and logs the specific error. Always back up before an upgrade using the SQLite backup API or a filesystem-level copy while the gate is stopped.

To roll back a ledger schema migration, restore from the pre-upgrade backup:

Terminal window
# Stop the (new) gate
# Replace the ledger file
# Stop the gate, then copy the backup over the active ledger
cp /backups/pre-upgrade-YYYYMMDD.db "$(latchgate config get ledger_db_path)"
# Start the (old) gate

Receipt signing keys are forward-compatible via the JWKS file. When you rotate or add keys, the old public keys remain in the JWKS so old receipts stay verifiable.

Never delete a verifying key from receipt-keys.jwks unless every receipt signed with that key has already been exported and verified externally. Losing a verifying key makes historical receipts unverifiable.

Grant signing keys do not require historical preservation — grants are short-lived (minutes) and expire long before any key rotation. A rotated grant key can be safely replaced.

latchgate config validate checks the current latchgate.toml against the installed binary’s config schema. If the binary requires a new field or a renamed field:

✗ unknown field 'old_name' (did you mean 'new_name'?)

Use latchgate config set new_name <value> to apply the rename — the CLI preserves comments and formatting. Never edit the TOML by hand when the CLI can do it; manual edits risk config drift.

The REST API follows the /v1/ prefix convention. Breaking changes to request/response shapes within /v1/ are avoided. When a breaking change is necessary, a new prefix (/v2/) is added and /v1/ remains supported for at least one minor version cycle.

SDKs pin to a specific API prefix. An SDK built for /v1/ continues to work with a gate that serves both /v1/ and /v2/.

If an upgrade fails health checks or exposes a regression:

  1. Drain and stop the new gate (same procedure as upgrade).
  2. Restore the ledger backup from step 1 of the general procedure:
    Terminal window
    # Stop the gate, then copy the backup over the active ledger
    cp /backups/pre-upgrade-YYYYMMDD.db "$(latchgate config get ledger_db_path)"
  3. Reinstall the previous binary:
    Terminal window
    brew install latchgate-ai/tap/latchgate@PREVIOUS_VERSION
  4. Restart and verify.

In-flight approvals issued by the newer version may not be readable by the older version. Those approvals expire (default 5 min TTL) and must be re-submitted by the agent.

Downgrading past a ledger schema migration requires the pre-upgrade backup. Running an older gate against a newer ledger is not supported — the gate refuses to start if it detects an unknown schema version.

Keep pre-upgrade backups for at least 30 days after any major version upgrade.

Subscribe to releases:

For production deployments, pin to a specific version tag rather than :latest. Test upgrades in a staging environment that mirrors production before rolling forward.