Files

47 lines
3.2 KiB
Markdown

# PostgreSQL migrations
Crank has one append-only migration authority in `crank-registry`. The Admin and MCP services run a read-only compatibility preflight; only the one-shot `crank-migrate` process may execute DDL.
For an existing installation, always run: read-only `preflight`, verified PostgreSQL and artifact-storage backup, `plan --check`, controlled `apply`, then a final `preflight`. Exit code `2` from CLI preflight means migration is required; exit code `1` blocks mutation until the reported condition is resolved.
Source command:
```bash
cargo run -p admin-api --bin crank-migrate -- plan --check
docker compose -f deploy/community/docker-compose.yml \
--env-file deploy/community/.env.example \
run --rm migrate crank-migrate preflight
```
The migrator reads only database configuration and retries connection for a bounded startup window. Diagnostics contain stable `code`, `stage`, nullable `version`, and `recovery`, never raw SQL, driver output, database URLs, credentials, or row data.
Published migrations are immutable and checksummed. Partial schema, unknown extension provenance, checksum drift, and future versions fail closed. Automatic down migrations, `--force`, destructive rollback, and arbitrary SQL input are not supported. Full N/N-1 upgrade and rollback qualification belongs to Story 7.2.
Version 3 adds nullable canonical Trace ID storage and partial Request/Trace indexes. New application writes provide both identities; historical rows remain honestly nullable and are never assigned fabricated traces.
Version 4 freezes version-local Operation identity and provenance. Legacy versions are marked as migration-time observations rather than fabricated history. PostgreSQL rejects updates or cascade deletion of Published payloads; later edits append a new Draft revision.
Version 5 (`execution-outcome-v5`) adds nullable exact Operation version,
execution stage, stable error code, retryability, and outcome certainty to
Invocation History. Legacy v4 rows remain `NULL`; no classification is fabricated.
Version 7 (`master-key-identity-v7`) adds durable master-key identity and
operator-controlled rotation state.
Version 8 (`admin-auth-lifecycle-v8`) adds one-time local bootstrap contracts, <!-- community-scope: allow=one-time-token -->
CSRF-backed browser sessions, login backoff, and bounded admin auth audit.
Production first-admin setup uses `crank-migrate admin-auth bootstrap-create`
plus the `/login` bootstrap flow, not a static startup password.
Lost Admin password recovery uses `crank-migrate admin-auth recover` with
local secret files and active master-key identity verification; it revokes
browser sessions and never prints password, pepper, master key, Secret plaintext,
or ciphertext.
Version 11 (`onboarding-product-events-v11`) adds nullable exact MCP key
provenance to Invocation History, immutable workspace-scoped local ProductEvents,
and daily eligible-denominator rollups. Historical and externally verified rows
remain honestly unscoped; no raw key, invocation payload, or external analytics
export is introduced.
For the complete ledger inventory, recovery table, and authoring rules, see the canonical [Russian operator contract](../migrations.md).