# Migrating to the Federated Tier > **KBN-101-07 ownership:** This active documentation is a **non-operative KBN-101 > contract** until KBN-101-02/-03/-05/-06 land and KBN-101-08 activates an exact reviewed > release. The commands below describe the produced interface only. Do not run them on the > current branch or replace them with direct PostgreSQL, raw SQL, legacy storage migration, or > credential-on-argv procedures. ## Required activation sequence The deployment control plane executes, in order: external privileged bootstrap; verified TLS and roles; `mosaic-db-migrator --run`; `mosaic-db-migrator --verify`; then Gateway readiness. The runner is the only attestation producer after its verified TLS, identity, manifest, and schema checks. A data importer is never a schema bootstrap, extension installer, repair command, or DDL consumer. ## Target material contract KBN-101-05 obtains the target URL from Vault KV-v2 `secret-{env}/mosaic-stack/database/importer`, key `url`, and reads its authenticated version from the same successful response `data.metadata.version`. A hash or DSN byte sequence is not a provider version. The renderer treats URL bytes and provider version as one generation, writes a temporary generation directory with fsync plus atomic rename, and creates separate immutable consumer mounts. Swarm uses distinct versioned secret/config references. A deployment cannot mix generations. | Consumer | Permitted material | | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Migrator-attestation producer (`10003:10003`) | Its own migration URL/CA; read-only `/run/secrets/mosaic-migrate-target-url` and `/run/secrets/mosaic-migrate-target-version`, each `0400`, solely to bind; producer-only attestation output at `/run/mosaic-attestations-producer/migrate-target.v1.json`; root-wrapper-only signing key. It never connects with, uses, exports, logs, or forwards the importer URL/version. | | Privileged deployment handoff controller | After runner success and before importer creation, it receives only root-owned non-secret expected provider-version/URL-SHA-256/generation descriptor and pinned public verifier key—not URL bytes or private key. It safe-opens/verifies descriptor and producer artifact, copies exact bytes to a new importer-only mount with fsync/atomic rename, sets `10002:10002` `0400`, seals it read-only, and refuses importer start on any partial/wrong-generation/wrong-owner/mode result. | | Importer (`10002:10002`) | Its own immutable `0400` copies at the same URL/version paths; CA at exact `DATABASE_TLS_CA_CERT_PATH=/run/secrets/mosaic-db-ca.crt`; pinned Ed25519 public key; read-only `/run/mosaic-attestations/migrate-target.v1.json` supplied only by the sealed handoff. | | Gateway/runtime/unrelated container | No importer URL/version, importer artifact, attestation private key, or unrelated CA mount. | The migrator and importer safe-open URL, provider-version, attestation, and public-key files only with `O_RDONLY|O_CLOEXEC|O_NOFOLLOW`; they validate from the opened fd that the file is regular, has its expected owner/mode and link count one. The migrator digests only that URL fd for binding, then zeroizes/closes it. The importer reads URL bytes once into protected memory, validates the signed binding and exact CA before connecting from those same bytes, then zeroizes/closes every fd. It neither logs nor exposes a URL/version/attestation/key oracle. ## Produced command interface After activation and only after approved target preparation, the future interface is: ```bash mosaic-db-migrator --run mosaic-db-migrator --verify mosaic storage migrate-tier --to federated \ --target-url-file /run/secrets/mosaic-migrate-target-url \ --target-attestation-file /run/mosaic-attestations/migrate-target.v1.json \ --dry-run ``` The provider-version file is fixed deployment material, not argv. This connecting dry-run consumes its nonce; before an actual copy, obtain fresh `mosaic-db-migrator --verify` and a new sealed handoff. The runner uses its migration identity; the importer connects only as non-DDL `mosaic_data_importer` and only after all pre-connect validation. After verified TLS and before DML it compares PostgreSQL system ID, database OID, `current_user`, CA/SPKI, and manifest/schema fingerprints to the artifact. ## Required refusals and evidence KBN-101-02/-03/-05/-06 must prove, with stable sanitized errors, that no target connection occurs for missing/unsafe URL/version/attestation/public-key files; symlink, hardlink, owner, mode, or TOCTOU violations; mixed URL/version generations; missing/wrong CA mount; stale/replayed/tampered or revoked-key artifacts; provider rotation/revocation; wrong TLS/server/database/role/manifest binding; raw `--target-url`; `DATABASE_URL` fallback; runtime/owner identity; consumer leakage; or any DDL attempt. Post-connect identity mismatch closes with zero DML/DDL. Tests also prove no forwarding, child environment, logging, or error oracle leaks URL/version/key/artifact contents. The attestation is credential-free JCS with detached Ed25519 signature and binds issued/expiry, nonce, authenticated provider version, exact URL-fd SHA-256, TLS host/port/database, CA/SPKI, PostgreSQL system ID/database OID, importer role, manifest/schema, and producer identity. Provider version rotation invalidates an old artifact and requires a fresh rendered generation plus runner verification. ## Actual copy after dry-run After reviewed dry-run, obtain the required fresh verification/attestation generation, then use: ```bash mosaic-db-migrator --verify mosaic storage migrate-tier --to federated \ --target-url-file /run/secrets/mosaic-migrate-target-url \ --target-attestation-file /run/mosaic-attestations/migrate-target.v1.json \ --yes ``` The dry-run artifact is terminally replayed and must be rejected; `--yes` bypasses no file, generation, signature, TLS, identity, or DDL control. ## Data boundary and recovery The importer has only an allowlisted mutable-table DML registry. It has no grant for immutable KBN relations, schemas, roles, memberships, extensions, catalogs, or the Drizzle ledger. Source PGlite uses its explicit local directory and does not make a PostgreSQL URL fallback valid. A failed or ambiguous migration is a control-plane incident: preserve sanitized evidence, retain the approved backup/rollback state, and retry only after independent review. Never inspect, unlock, repair, or initialize the target with ad hoc SQL or copied credentials.