Build Rust-owned database bootstrap and development environment
## Outcome Replace the Python/shell and pinned-Go-dependent development fixture workflow with a Rust-owned, reproducible development environment. Rust must initialize a brand-new compatible PostgreSQL database, generate all required synthetic instance/key/policy/user/client state, and run the complete development and test stack without building or starting Go. The production server remains unable to mutate schema automatically. ## Current problems - `test_support/create_synthetic_fixture.py` and `test_support/run_synthetic_server.py` contain roughly 700 lines of imperative Docker, credential, process, proxy and fixture orchestration. - Normal fixture creation depends on building and running the pinned Go server to install schema, projections, keys and initial instance state. - Synthetic-only target validation is coupled into the normal `identity-server serve` path, while production deployment should contain only runtime compatibility/configuration checks. - Fixture lifecycle, interactive development, integration tests and the temporary Go rollback oracle are entangled. ## Architecture decisions - Rust becomes the authority for bootstrapping new databases. Go is not used by ordinary fixture creation, development startup, Rust integration CI or browser testing. - Bootstrap is an explicit one-shot operation for an empty database. `identity-server serve` must never create, migrate or repair schema. - During the same-database Go rollback window, bootstrap installs one reviewed compatibility schema version without a general migration framework. Existing production databases are not modified. - `zitadel-postgres` continues to own PostgreSQL SQL and compatibility encoding. Bootstrap-only SQL/APIs are isolated behind a non-production feature or tooling boundary; domain/application crates remain independent of PostgreSQL and Docker. - A separate Rust development tool (`devctl`/`xtask`, exposed as `cargo dev …`) owns Docker Compose lifecycle, local secret files, readiness, safe reset/destruction and test orchestration. The production server binary and image do not expose fixture lifecycle commands or synthetic data assumptions. - Docker Compose describes services, health checks, networks, mounts and loopback ingress. Rust tooling performs only the stateful decisions Compose cannot express safely. - The attested pinned Go implementation remains temporarily only as an explicit rollback compatibility oracle and deployable rollback artifact. It is not the schema, key or fixture authority and is never part of normal `cargo dev init/up/test`. ## Canonical schema - Capture a schema-only definition from the approved, fully synthetic baseline—never from the private production dump or any production-data restore. - Check in a readable, reviewable and versioned schema definition containing required schemas, extensions, tables, indexes, constraints, functions, triggers and event-store behavior. It must contain no rows, credentials, key material, ownership tied to a developer machine, or environment-specific settings. - Normalize and test the definition so a fresh PostgreSQL 17 database produces the expected structural contract. Record provenance and fingerprint in the compatibility manifest without treating the synthetic fingerprint as proof of current production compatibility. - Bootstrap refuses a database containing application schemas/objects or an existing identity marker. It does not upgrade, repair, overwrite or drop an initialized database. - Use an existing compatible metadata location such as the database comment for bootstrap version/provenance; do not add an application-only schema table while same-database Go rollback remains required. ## Rust bootstrap behavior A single transaction where PostgreSQL permits must: - install the canonical compatibility schema and event-store functions; - generate a fresh master-key-compatible encryption hierarchy and active/retained OIDC signing material using secure randomness and compatible envelopes; - create the initial instance, localhost domain, default organization and generated verified organization domain state; - create required login, password complexity, password age, lockout, notification, OIDC, secret-generator and branding defaults; - create the synthetic administrator, service user, PAT, project, public OIDC client and exact localhost callback/logout configuration; - seed the representative fake organizations/users needed by existing authorization, OIDC, administration, setup/email and concurrency suites through shared command/repository behavior rather than parallel raw test-only semantics; - keep stored SMTP/SMS providers empty and emit only reserved-domain identities and local/test destinations; - write mode-0600 generated credentials and mode-0700 state directories, with secrets redacted from logs/errors; - inspect and verify the final schema, key access, instance resolution, policy state, PAT authentication and fixture provenance before reporting success. Bootstrap failure must leave no partially initialized identity database. Retrying after an uncertain failure must fail safely and tell the operator to destroy/recreate the dedicated development volume rather than guessing at recovery. ## Development environment Provide a concise command surface, preferably through `.cargo/config.toml` aliasing a Rust tooling crate: - `cargo dev init`: create the dedicated resources and Rust-bootstrap a new synthetic fixture; - `cargo dev up`: start Rust identity, Mailpit and optionally the diagnostic relying party; - `cargo dev down`: stop interactive services without deleting the fixture; - `cargo dev status`: report services, provenance and safe local URLs without secrets; - `cargo dev reset`: remove only owned development resources and recreate the fixture; - `cargo dev destroy`: remove only labelled/Compose-owned development resources and private generated state; - `cargo dev test`: stop conflicting interactive services and run the guarded Rust database/contract suites; - `cargo dev compat-go`: explicitly run the temporary pinned-Go exclusive-writer restart/readback gate. Use a dedicated Compose project and an internal, egress-denied network. PostgreSQL must not publish a TCP port; native tooling/tests may use a private bind-mounted Unix socket. Identity, Mailpit and the diagnostic RP expose ingress only on host loopback. Containers run non-root where practical, with dropped capabilities, `no-new-privileges`, read-only filesystems and bounded tmpfs mounts. Pin third-party images by immutable digest and use declarative health checks. Normal development must not require ad-hoc host proxy processes. ## Safety constraints - Never read, restore or clone the private production dump or any real-data database. - Refuse remote Docker contexts and unexpected resource ownership for destructive development commands. - Reset/destroy operations act only on the exact dedicated Compose project/resources after verifying labels and paths; they never enumerate and remove unrelated PostgreSQL/Docker resources. - Database-writing tests retain in-process provenance, database-name/role/host and explicit write-opt-in guards, and mutate only disposable clones. - Generated callbacks, mail recipients and providers remain loopback or reserved test destinations; the development network has no outbound access. - Bootstrap and development tooling have bounded waits, cleanup on failure, redacted private diagnostics and actionable errors. ## Temporary Go compatibility boundary - Produce or consume one immutable, attested OCI image for baseline commit `4877cddfba02c3fed166a35e19927360dd8467fe`, pinned by digest and source/binary metadata. Developers do not generate Go/protobuf/static assets during ordinary work. - Only `cargo dev compat-go` and the dedicated trusted compatibility CI job may start it, always against a disposable clone with Rust and Go acting as exclusive writers. - The gate must prove pinned Go can start on a Rust-bootstrapped database, read Rust-created users/organizations/clients, validate compatible PAT/token/session state, exchange a pending Rust authorization code, and write state Rust subsequently honors, without schema changes. - Document removal of the image/job/tooling after the production rollback window closes. ## CI and validation - The normal CI job bootstraps PostgreSQL entirely through Rust and runs all repository, HTTP, real `Zitadel::Client`, setup/email, OIDC lifecycle, administration and browser-supporting suites without Go, Python orchestration or production-derived secrets. - The temporary Go compatibility job is visibly separate, mandatory for relevant compatibility changes, and consumes only the attested image plus Rust-generated synthetic data. - Add negative tests for non-empty databases, partial schema, wrong marker/version, remote/production-like targets, unsafe callbacks/providers, unowned resources, malformed private state and interrupted bootstrap. - Verify bootstrap/reset determinism, exact schema fingerprint, identical locale keys, unchanged schema after mutation suites, and reproducible cleanup. - Run formatting, strict all-target/all-feature Clippy, workspace tests, database suites, dependency policy, container build and browser acceptance for password/setup/passkey/admin flows. ## Removal and documentation - Remove `test_support/create_synthetic_fixture.py`, `test_support/run_synthetic_server.py` and their Python cache/artifacts after feature parity. - Remove the local pinned-Go build from normal setup and CI; retire `test_support/build_pinned_go.sh` once the attested compatibility image path is operational. - Consolidate duplicated Docker/process/private-file helpers currently spread across Python and Rust test support. - Rewrite README development, integration-test and rollback instructions around `cargo dev`; remove stale restored-fixture terminology and environment variables no longer meant for direct operator use. - Keep production deployment configuration separate from development Compose and synthetic tooling. ## Acceptance criteria - From a clean checkout with Rust, Docker and Docker Compose—but without Go or Python—a developer can initialize the database and start the complete local identity/Mailpit/RP environment through the documented `cargo dev` commands. - A fresh Rust bootstrap has no real data or external destinations, resolves/decrypts its generated keys, authenticates its generated PAT, passes exact schema/provenance checks and supports all existing Rust application flows. - Re-running bootstrap on a non-empty or partially initialized database fails without mutation; reset/destroy cannot touch unowned resources. - Normal CI and all Rust database/client/browser suites have no pinned-Go dependency. The only remaining Go use is the isolated temporary rollback gate. - Pinned Go starts successfully against a disposable clone of the Rust-bootstrapped database and the bidirectional read/write compatibility gate passes with no schema drift. - The production `identity-server` binary has no required fixture ID, synthetic role/database check, fake-domain inventory check or loopback-only SMTP restriction; it retains schema/key/instance/configuration verification and never bootstraps automatically. - Existing production remains an in-place, no-migration cutover target. No production data is used to construct or test the new bootstrap. - Python fixture runners and ordinary local Go build requirements are removed, documentation is current, and the workspace/release gates pass. ## Non-goals - Migrating or rewriting the current production database. - Automatically upgrading an initialized database. - Restoring or sanitizing the private production dump. - Reproducing excluded ZITADEL APIs/subsystems merely to make bootstrap resemble Go internals. - Removing the production rollback artifact before the agreed rollback window closes.
Checklist
9 of 9 complete- Capture, normalize and review a data-free canonical compatibility schema from the approved synthetic baseline; record provenance and verify deterministic PostgreSQL 17 fingerprinting.
- Implement the empty-database-only Rust bootstrap boundary with transactional schema installation, strict non-empty/partial/unsafe-target refusal and failure-atomic behavior.
- Generate compatible instance, encryption/signing keys, policies, administrators, service/PAT, organizations, projects/OIDC clients and representative fake users entirely in Rust, then verify key/PAT/schema/provenance invariants.
- Build the Rust `cargo dev` lifecycle tool and hardened Docker Compose environment for init/up/down/status/reset/destroy/test with internal networking, private PostgreSQL socket, loopback ingress and safe secret handling.
- Decouple synthetic fixture checks from production `identity-server serve`; keep production-neutral schema/key/instance/config validation and ensure the production image excludes development lifecycle tooling.
- Port all guarded repository, API, administration, setup/email, OIDC lifecycle, real Ruby client and browser-supporting suites to the Rust-bootstrapped fixture and make normal CI independent of Go and Python orchestration.
- Replace local pinned-Go builds with one immutable attested compatibility image and verify the explicit exclusive-writer bidirectional rollback gate against disposable Rust-bootstrapped clones without schema drift.
- Remove the Python fixture runners and obsolete shell/env pathways, consolidate duplicated orchestration helpers, and rewrite development/testing/rollback documentation around `cargo dev`.
- Pass final safety negatives, deterministic reset/cleanup, formatting, strict Clippy, workspace and database suites, dependency policy, production container build and relevant browser acceptance from a clean checkout without Go or Python.
- Area
- Kaukus
- Kind
- Feature
- Priority
- High
- Task ID
tsk_tn3c5exrdq- Updated