Hub RFC 005 migration manifests

RFC-005 — Migration Manifests for Upgrade Chain Automation

Field Value
RFC RFC-005
Title Migration Manifests — Automated min_upgrade_from Declaration
Author Koder Engineering
Date 20260416
Status Draft
Depends on RFC-004 (Upgrade Chains)

Table of Contents

  1. Abstract
  2. Motivation
  3. Design
  4. Worked Example
  5. Validation Rules
  6. Security Considerations
  7. Compatibility
  8. Alternatives Considered

1. Abstract

RFC-004 introduced min_upgrade_from as a manually declared field passed via --min-upgrade-from at publish time. This RFC adds a *igration manifest*— a structured TOML file committed alongside the code — from which publish.sh reads min_upgrade_from automatically, and which Koder Flow can validate in CI before the release is created.

The goal is to make the upgrade chain constraint *o-located with the breaking change*(same commit, same diff review) rather than a publish-time memory exercise.


2. Motivation

2.1 The problem with pure manual declaration

RFC004 requires the publisher to remember to pass `minupgrade-from when calling publish.sh`. The constraint is invisible during code review and easy to forget. A missed declaration silently breaks users who skip versions.

2.2 Why co-location matters

The moment a developer deletes the legacy migration code or changes a data format, that is the right moment to declare the constraint — in the same PR, in the same file tree. A manifest file committed alongside the breaking change:

  • Appears in the PR diff and is reviewed as code.
  • Is version-controlled and auditable via git log.
  • Can be linted in CI before the release reaches users.
  • Removes the publish-time memory burden.

3. Design

3.1 Manifest File Format

A TOML file with a single [upgrade] table:

# migrations/v3.0.0.toml
[upgrade]
min_upgrade_from = "2.0.0"
reason = "removes legacy binary config reader; JSON migration code lives in v2.x"

Fields:

Field Type Required Description
min_upgrade_from string Yes Semver lower bound (same semantics as RFC-004)
reason string No Human-readable explanation — shown in admin review queue

3.2 File Location

<repo-root>/
  migrations/
    v2.0.0.toml     ← no constraint (absent = no constraint)
    v3.0.0.toml     ← declares min_upgrade_from = "2.0.0"
    v3.1.0.toml     ← absent = no constraint for v3.1.0
  • One file per version that carries a constraint.
  • Versions with no constraint have no manifest file (absence = min_upgrade_from: null).
  • The file name *ust*match the release version exactly: v{VERSION}.toml.

3.3 publish.sh Auto-Detection

Before sending the publish request, publish.sh checks for the manifest:

REPO_ROOT/migrations/v{VERSION}.toml

If found and --min-upgrade-from was *ot*passed explicitly on the command line, the script reads min_upgrade_from from the manifest and passes it to the API. Explicit --min-upgrade-from always takes precedence (allows overrides in automated pipelines).

*esolution order:*

  1. --min-upgrade-from CLI flag (explicit, highest priority)
  2. migrations/v{VERSION}.toml manifest (auto-detected)
  3. None (no constraint)

3.4 Store Backend Handling

The publish API (POST /api/v1/publish/:slug) already accepts min_upgrade_from as a form field (RFC-004 §5.3). No change needed at the API level — publish.sh passes the value regardless of whether it came from the CLI flag or the manifest.

Optionally, the API can also accept the manifest file itself as a multipart upload (-F "migration_manifest=@migrations/v3.0.0.toml"), which allows richer server-side validation and preserves the reason field for the admin review queue. This is left as a backend enhancement (see §3.5).

3.5 Koder Flow Integration

When a release is created in Koder Flow (via UI or API), Flow can:

*. Surface the manifest in release notes*

If migrations/v{TAG}.toml exists in the repo at the release tag, Flow displays min_upgrade_from and reason prominently in:

  • The release creation confirmation page.
  • The release details page.
  • The admin review queue (Koder Hub side).

*. CI lint step*

A pre-built lint action validates the manifest on every PR that touches a migrations/ file:

# .koder-ci.yml (example)
lint-migration-manifest:
  run: khub-lint migrations/

Validation checks:

  • min_upgrade_from is valid semver.
  • min_upgrade_from < the declared version (extracted from file name).
  • The referenced version exists in the published catalog (warning, not error).

*. Release webhook*

When a release is tagged, Flow can call the Store publish API with the manifest data as an additional form field, enabling the Store to store reason for admin review display.


4. Worked Example

Publisher is releasing v3.0.0 which removes the binary config reader:

# 1. Code change + manifest committed in the same PR:
git add src/config/json_reader.go migrations/v3.0.0.toml
git commit -m "feat: remove legacy binary config reader (requires v2.0.0 migration)"

# 2. Create release (tag + Flow release):
git tag products/dev/store/v3.0.0
git push origin products/dev/store/v3.0.0

# 3. Publish — no --min-upgrade-from needed:
publish.sh --slug my-app --version 3.0.0 --version-code 30 --file my-app.deb
# → Auto-detected min_upgrade_from=2.0.0 from migrations/v3.0.0.toml
# → Publishing my-app v3.0.0 [min_upgrade_from=2.0.0]

5. Validation Rules

Rule Level Description
Valid semver Error min_upgrade_from must be parseable semver
min_upgrade_from < version Error Prevents self-referential constraints
Referenced version published Warning Version in constraint may not exist yet (outoforder publish)
reason present Warning Recommended for admin review clarity
File name matches release version Error v3.0.0.toml must be published with --version 3.0.0

6. Security Considerations

The manifest is source-controlled and goes through code review — this is strictly safer than a publish-time CLI flag that bypasses review. The same publisherabuse mitigations from RFC004 §8.1 apply (admin review queue, yank protections).


7. Compatibility

  • *pps without manifests:*publish.sh finds no file, sends no

    min_upgrade_from — identical to current behavior.

  • *pps with --min-upgrade-from flag:*flag wins over manifest — no

    regression for existing pipelines.

  • *reRFC005 publish.sh:*ignores manifests silently; the publisher

    must pass --min-upgrade-from manually as today.


8. Alternatives Considered

A. Embed manifest inside the package artifact (.deb, .apk)

Store reads it from the binary at publish time.

*ejected for v1:*Requires modifying the build pipeline for every app. The source-repo manifest approach requires zero changes to how packages are built.

B. Heuristic artifact diff (automatic, no manifest)

Flow diffs consecutive release artifacts looking for removed files, schema changes, etc.

*eferred:*High false-positive rate; cannot reliably infer safe waypoints from binary diffs alone. Useful as a suggestion layer on top of manifests, not as a replacement. Tracked separately.

C. In-code annotation (@requiresUpgradeFrom("2.0.0"))

Source annotation that a static analysis tool reads.

*ejected:*Language-specific, requires SDK integration per platform, fragile across refactors. TOML manifest is language-agnostic.

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/hub-RFC-005-migration-manifests.md