Release & Upgrade Policy

This document is for maintainers and operators preparing or consuming releases. It defines upgrade expectations, migration and rollback behavior, and a repeatable release checklist.

Security Contact

Do not post vulnerability details in public issues.

Upgrade Statement

Current status: Carapace ships a stable release line, beginning with v0.1.0.

Stable-release upgrade policy is active:

Historical preview-tag guidance:

Versioned N-1 Contract (stable channel)

Surface N-1 -> N expectation Breaking-change requirement
Config format (config.json5) New stable versions document the accepted config shape for that release. If a key/shape is removed or semantics change, provide operator steps and rollback guidance.
State files (state_dir) New stable versions read prior stable state and perform safe migrations where needed. If migration is not automatic, ship operator migration steps and rollback steps.
Session/task persistence (sessions/, tasks/) New stable versions can read current persisted session/task data or fail closed with actionable remediation. If format changes reject existing data, provide conversion path and recovery procedure from backup.

Contract boundary:

Migration Behavior

General migration rules:

  1. Prefer automatic migration only when behavior is deterministic and reversible from backup.
  2. Any migration that can change persisted state must be documented in release notes.
  3. If migration fails, fail closed with an actionable error instead of silently continuing in a mixed state.

Operator expectation:

Rollback Runbook

Use this when an upgrade causes a regression.

  1. Stop Cara.
  2. Reinstall the previous known-good binary (pinned tag URL).
  3. Restore backup created before the upgrade:
    • cara restore ./carapace-backup.tar.gz
  4. Start Cara.
  5. Verify:
    • cara status --port 18789
    • cara verify --outcome auto --port 18789
    • cara verify --outcome autonomy --port 18789

Recovery-time target:

Downgrade Forward-Compat Semantics

When an older binary reads marker files written by a newer daemon (the precise scenario rollback exists to handle), Cara's custom deserializers prevent hard-parse failures from variants the older code didn't ship:

In all three cases the marker file ITSELF is preserved on disk so an operator can re-upgrade and let the newer binary process the marker according to its actual semantics. Do NOT manually edit these JSON files to "fix" the warn-logged values; the older binary's fall-back is the documented safe operation while the rollback decision is being made.

Updater Authenticity and Resume Contract

Updater behavior is fail-closed by policy:

  1. cara update and WS update.install both require Sigstore bundle verification for the target binary (<asset>.bundle).
  2. Verification policy is strict:
    • OIDC issuer must be https://token.actions.githubusercontent.com
    • certificate identity must match this repo release workflow for the target tag.
  3. Missing/invalid bundle, trust-chain failure, issuer mismatch, or identity mismatch must stop install before apply.
  4. SHA256SUMS.txt verification is a secondary integrity check when present, not a substitute for authenticity verification.

Resume behavior:

  1. Update transactions persist at {state_dir}/updates/transaction.json.
  2. Transaction phases are persisted across restarts (created, downloading, downloaded, verified, applying, failed, applied).
  3. Startup performs bounded auto-resume for retryable interrupted updates.
  4. Non-retryable failures stay terminal and require operator intervention.

Release Notes Template

Every release should include these sections:

## Summary
- High-level changes in this release.

## Breaking Changes
- What changed, who is affected, and impact.

## Migration Steps
- Exact commands or file changes required after upgrade.

## Rollback Steps
- Exact steps to return to previous known-good version.

## Security
- Security fixes, hardening changes, and advisory references.

## Verification
- Links or commands for signature/checksum verification.

## Known Caveats
- Remaining limitations or partial areas relevant to operators.

Curated release notes are versioned in-repo at:

Examples:

The tag-triggered release workflow publishes that exact file and fails closed if it is missing.

Historical release-note files are immutable once their tag has shipped. Draft notes for a future release can be kept locally while audit work is in progress, but the committed docs/releases/<tag>.md should be added only during the release-prep/tag flow for that release.

Reproducible Release Checklist

  1. Confirm master is green (CI + CodeQL + required checks).
  2. Confirm no open critical/high security findings on master.
  3. Confirm docs are current for install, ops, and security behavior.
  4. Commit docs/releases/<tag>.md with all required release-note sections.
  5. Create annotated tag from master:
    • git tag -a vX.Y.Z -m "vX.Y.Z"
    • For intentional prereleases only: vX.Y.Z-previewN
  6. Push tag:
    • git push origin <tag>
  7. Wait for .github/workflows/release.yml to complete.
  8. Verify release artifacts are published (all target binaries + signatures + checksums).
  9. Verify published artifact authenticity/checksum workflow against the release (run from repo root).
    • ./scripts/smoke/verify-release-artifacts.sh
    • Optional overrides:
      • RELEASE_TAG=vX.Y.Z ./scripts/smoke/verify-release-artifacts.sh
      • CARA_ASSET=cara-x86_64-linux ./scripts/smoke/verify-release-artifacts.sh
  10. Smoke-check the published binary on at least one Linux and one macOS path.
  1. Confirm release notes contain all required sections above.
    • The published GitHub release body should match docs/releases/<tag>.md.

Distribution Notes