8.1 KiB
Миграции PostgreSQL
Crank использует единственную append-only migration authority в crank-registry. admin-api и mcp-server выполняют только read-only preflight. DDL применяет one-shot binary crank-migrate, который Community Compose запускает до readiness сервисов.
Безопасная последовательность оператора
Для source Compose замените <compose> на:
docker compose -f deploy/community/docker-compose.yml --env-file deploy/community/.env.example
Для image Compose используйте docker compose -f deploy/community/docker-compose.images.yml --env-file .env. Перед обновлением уже работающей установки выполните строго:
- Read-only preflight:
<compose> run --rm migrate crank-migrate preflight. Exit0означает current, exit2— ожидаемуюmigration_required; exit1запрещает mutation до устранения причины. - Создайте и проверьте согласованный backup PostgreSQL и artifact storage. Для первой пустой установки зафиксируйте, что восстанавливать нечего.
- Проверьте immutable plan:
cargo run -p admin-api --bin crank-migrate -- plan --checkв source checkout либо<compose> run --rm migrate crank-migrate planдля образа. - Примените sequence:
<compose> run --rm migrate crank-migrate apply. - Повторите preflight и убедитесь в
{"status":"current","version":3}. - Только теперь запускайте long-running services:
<compose> up -d.
Обычный up также содержит обязательный migration job, но при upgrade он не заменяет предварительные preflight и backup. Migrator делает до десяти bounded попыток подключения с секундной паузой и затем безопасно завершается ошибкой.
Команда читает только CRANK_DATABASE_URL/POSTGRES_*. Master key, session secret, bootstrap password, MCP credentials и другие service secrets не входят в её config projection.
Фактический brownfield inventory
| Источник | Исторический владелец/lock | Известный контракт |
|---|---|---|
__crank_core_migrations |
crank-registry, session lock 0x4352414e4b |
columns version, description, checksum, applied_at; v1 checksum crank-community-baseline-v1 |
__crank_mcp_migrations |
MCP session store, session lock 0x4352414e4b4d4350 |
columns version, checksum, applied_at; v1 checksum mcp-transport-sessions-v1 |
__crank_ext_migrations |
прежний RegistryExtension, без общего lock |
legacy columns extension_name, version, applied_at; checksum отсутствовал |
__crank_migrations |
canonical MigrationAuthority, transaction lock 0x4352414e4b4d4947 |
append-only sequence с version/name/checksum/phase/compatibility |
__crank_migration_legacy_audit |
canonical MigrationAuthority |
только доказуемо сопоставленное legacy provenance |
Legacy extension row без зарегистрированного exact (name, version, checksum) несовместим. Community пока не публиковала extension migrations, поэтому authority не выдумывает им checksum и блокирует такие строки с legacy_conflict.
Контракт sequence
Machine plan находится в schemas/migration-sequence.json и проверяется командой:
cargo run -p admin-api --bin crank-migrate -- plan --check
- V1 — immutable brownfield baseline с историческим ledger token и отдельным exact-source SHA-256.
- V2 — единый exact-byte expand SQL artifact, создающий canonical ledgers и MCP session schema; его SHA-256 закреплён в executable descriptor.
- V3 — append-only expand для независимого nullable
invocation_logs.trace_id, canonical-format constraint и partial request/trace indexes; исторические строки остаютсяNULLбез fabricated backfill. - Каждая версия имеет contiguous
i64version, стабильное имя, lowercase SHA-256, owner, phase, explicit readable schema min/max и backfill policy. migrateтребует bounded cursor/batch policy;contractдополнительно требует tracked compatibility evidence и закрытого окна.- Добавление descriptor без executable implementation блокируется
invalid_contractдо DB I/O.
Legacy ledgers остаются readable. Down migration, destructive automatic rollback, ledger rewrite, --force и arbitrary SQL/path input отсутствуют. Полная N/N-1 upgrade/rollback qualification остаётся Story 7.2.
Диагностика и восстановление
CLI/stderr возвращают bounded JSON: code, stage, nullable numeric version, recovery. Database URL, credentials, raw SQL/driver body, row values и host paths не выводятся.
| Code | Значение | Безопасное действие |
|---|---|---|
schema_missing |
Service startup увидел пустую schema | Запустить controlled migration; не разрешать runtime DDL |
migration_required |
Schema отстаёт; preflight CLI завершает работу с exit 2 |
Проверить backup и выполнить controlled apply |
checksum_mismatch |
Artifact и ledger не совпали | Сначала проверить immutable application image/release manifest; восстанавливать БД только после доказанной ledger corruption |
partial_sequence |
Relation/ledger/structural fingerprint неполон | Не чинить вручную; сопоставить backup и matching artifact |
future_version |
База новее приложения | Установить matching application; не откатывать schema автоматически |
legacy_conflict |
Legacy provenance невозможно доказать | Сохранить backup и привлечь оператора |
lock_timeout |
Другой migration runner удерживает canonical lock | Дождаться завершения и повторить preflight |
apply_failed |
Transaction migration откатилась | Проверить matching artifact/backup, затем повторить preflight |
storage_unavailable |
PostgreSQL/transport недоступен | Проверить сеть/TLS/права; секреты в diagnostic не копировать |
config_invalid |
Database-only config невалиден | Исправить указанный config contract |
invalid_command |
Неизвестная CLI команда/аргумент | Использовать только plan, preflight, apply |
contract_drift |
Committed machine plan расходится с Rust authority | Перегенерировать только для новой append-only version и проверить diff |
invalid_contract |
Descriptor/implementation/window/evidence несовместимы | Исправить authoring contract до любого DB I/O |
Правила разработчика
- DDL, SQL migration assets и canonical advisory lock разрешены только в
crank-registry::migrations. - Schema развивается
expand → bounded/resumable migrate → evidence-gated contract. - Опубликованные source bytes/checksums не редактируются: добавляется новая version.
- Для каждой version обязательны fresh/current/concurrent/corrupt/rollback/data-preservation tests и explicit Community scope scan.