Contents

Migration model audit and pairing

Configure migration audit bootstrap, environment pairing and the Webapp Pack against the migration model contract.

migration_audit Bootstrap

migration_audit carries two kinds of row in two places. Rehearsal receipts are item evidence and live on the control plane that holds the item, keyed by project_id and model_name: yoke_core.domain.migration_rehearsal_evidence owns that location for the rehearsal that writes them and the evidence gate that reads them, so a project whose authority is a database the control plane cannot open is gated the same way as Yoke itself. Boot-apply rows live on the database being converged, written by yoke_core.domain.migration_boot_apply.apply_pending beside the ledger row they describe.

yoke_core.domain.migration_audit_schema.ensure_migration_audit_table(conn) (and its Postgres sibling) is the canonical idempotent helper; both writers call it before their first row, so operators and agents never provision migration_audit themselves. The migration-territory claim stays on the control plane too (LIVE_DB_MIGRATION:<model_name>).

Pairing Matrix

The wired pairings are:

authoritative_db.kind validation_surface.kind runner.kind
sqlite_file worktree_local_sqlite governed_migration_module
postgres external_validation governed_migration_module

Four vocabulary values are deliberately recognized but rejected until their complete pairing exists: authoritative DB mysql, validation surfaces staging_db and ephemeral_container, and runner external_adapter. They are not implied live pairings and must remain visible as explicit refusals.

The SQLite pairing is project-generic: webapp projects use it with project-local module paths and the app DB env var. The Postgres pairing is Yoke's authority shape — authoritative_db.kind="postgres" with the runner.config.modules_dir from its own capability payload and the YOKE_PG_DSN runner binding. Validation is external to this worktree-local provisioning surface; the authoritative DB location names a Postgres stack/output source:

The validator keeps this shape generic: it validates stack/output/database references, not Yoke-only endpoint literals. Local proof commands can bind the resolved DSN via YOKE_PG_DSN_FILE so secret-bearing DSNs stay in a restricted file instead of shell-expanded arguments. This pairing declares authority and validation bindings; other runner kinds are schema-reserved and rejected. The SQLite migration_model_defaults payload appears below under Webapp Pack Configuration.

Webapp Pack Configuration

The Webapp Scaffold Pack's app database is app-local SQLite. Yoke backlog and delivery state stay on the Postgres control plane — never aim Yoke operations at the app DB or the retired worktree-local data/yoke.db path. The pack's packs/webapp-scaffold/versions/1.1.2/settings-reference.json (Yoke source tree) carries a top-level migration_model_defaults block:

{
  "migration_model_defaults": {
    "default_model": "primary",
    "models": {
      "primary": {
        "authoritative_db": {
          "kind": "sqlite_file",
          "location": {"path": "app/data/app.db"}
        },
        "validation_surface": {
          "kind": "worktree_local_sqlite",
          "provisioning": {
            "path": ".yoke/validation.db",
            "recipe": "webapp_sqlite_empty"
          }
        },
        "runner": {
          "kind": "governed_migration_module",
          "config": {
            "modules_dir": "app/db/migrations",
            "connection_env_var": "APP_DB_PATH",
            "ledger": {
              "table": "applied_migrations",
              "entry_column": "migration_name",
              "digest_column": "content_sha256",
              "semantics": "membership",
              "serving_floor_column": "minimum_serving_version"
            }
          }
        }
      }
    }
  }
}
Migration pairing · Yoke