Development
Development
Section titled “Development”This page covers how to build, test, and contribute to DBCrust.
Prerequisites
Section titled “Prerequisites”- Rust — stable toolchain
- mise 2026.8.16+ — manages Commitizen, the Mr Boxington build cache and the other tools, and runs every task. You don’t have to install it: the repository’s
./bin/misewrapper downloads a pinned mise on first use. - Python 3.10+ — only needed for the Python bindings
# From the project root — install all managed toolsmise install
# No mise? Use the committed wrapper the same way, for every command on this page./bin/mise install./bin/mise run build:devOn first use in a clone, mise asks you to trust mise.toml (or run mise trust). ./bin/mise keeps its mise binary and tools in mise’s usual directories, so they are shared with a mise you install later. On Windows, run bin\mise.cmd.
mise install reads mise.toml and sets up:
| Tool | Purpose |
|---|---|
Mr Boxington (mbx) | Shared Cargo build cache — see Build cache |
| Bun | JavaScript runtime for the documentation site |
| Commitizen | Conventional commit helper |
| pkl | Configuration language |
| hk | Git hooks |
Rust build cache
Section titled “Rust build cache”The project-scoped mise wrapper routes Cargo through Mr Boxington. mise run tasks use it automatically; activate mise in your shell if you also want plain cargo commands to use the cache.
mbx doctor # verify Cargo and cache integrationmbx cache stats # inspect cache usagembx gc --dry-run # preview automatic cleanupSet MBX_DISABLE=1 for a one-off uncached Cargo command.
Building
Section titled “Building”mise run build:dev # debug build (fast compile)mise run build # release build (optimized)cargo run -- <url> # run directly without installingcargo install --path . # install to ~/.cargo/binThe binary is named dbcrust. A short alias dbc is also built (see src/bin/dbc.rs).
Desktop app
Section titled “Desktop app”mise run gui:dev # run the app (dev build, optimised dependencies)mise run gui:build # release buildmise run gui:test # backend tests (dbcrust-gui-core, no GPUI needed)mise run gui:lint # clippy on both GUI cratesmise run gui:screenshots # regenerate the docs/README screenshots headlesslymise run gui:bundle # macOS DBCrust.appThe app is two crates: gui/core (dbcrust-gui-core, plain Rust — workers, storage, models) and gui (dbcrust-gui, the GPUI Kit views). See gui/ARCHITECTURE.md.
See Desktop GUI for full details.
Python bindings
Section titled “Python bindings”mise run py:dev # maturin develop (editable install)mise run py:build # build wheelmise run py:test # run pytestpip install -e ./python # alternative: pip editable installBuild features
Section titled “Build features”The root crate (dbcrust) is split into Cargo features so a build only contains the engines and add-ons it needs. The default build is bundled: every engine and add-on DBCrust has shipped so far. Release binaries and Python wheels use bundled; the desktop app enables the same engines on dbcrust-drivers.
| Feature | What it enables | Pulls in |
|---|---|---|
bundled (default) | Everything below | — |
standard | postgres + mysql + sqlite (the slim preset) | sqlx |
postgres | PostgreSQL | sqlx, pgvector |
mysql | MySQL / MariaDB | sqlx |
sqlite | SQLite | sqlx (bundled libsqlite3) |
mongodb | MongoDB | mongodb, bson |
clickhouse | ClickHouse | clickhouse (pinned =0.15.1) |
elasticsearch | Elasticsearch | elasticsearch SDK |
white-dragon | White Dragon search SQL over HTTP | reqwest only |
redis | Redis / Valkey (redis://, rediss://) — in bundled, not in standard | redis (tokio + rustls/ring) |
mssql | SQL Server / Azure SQL (mssql://, sqlserver://) — in bundled, not in standard | vendored tiberius 0.13.0 (third_party/tiberius: rustls on ring only, see below) |
redshift | Amazon Redshift (redshift://) — in bundled, not in standard | sqlx PostgreSQL protocol (no extra crate) |
libsql | libSQL / Turso over HTTP (libsql://, turso://, libsql+http://) — in bundled, not in standard | reqwest only (hand-written Hrana client) |
influxdb | InfluxDB v1/v2/v3 (influxdb://, influxdb2://, influxdb3://) — in bundled, not in standard | reqwest (rustls/ring) and csv-core, both already in the tree |
s3 | Amazon S3, Cloudflare R2, MinIO (s3://, r2://, minio://) — opt-in: not in bundled, not in standard; needs Rust ≥ 1.94.1 | AWS SDK (aws-config, aws-sdk-s3, aws-smithy-http-client), rustls on ring only |
dynamodb | Amazon DynamoDB (dynamodb://, dynamodb+http://, ddb://) — opt-in: not in bundled, not in standard; needs Rust ≥ 1.94.1 | AWS SDK (aws-config, aws-sdk-dynamodb, aws-smithy-http-client), rustls on ring only |
cloudwatch | Amazon CloudWatch Logs (cloudwatch://, cloudwatch+http://, cwlogs://) — opt-in: not in bundled, not in standard; needs Rust ≥ 1.94.1 | AWS SDK (aws-config, aws-sdk-cloudwatchlogs, aws-smithy-http-client), rustls on ring only |
aws | the AWS connectors as a group (s3, dynamodb, cloudwatch) — opt-in, Rust ≥ 1.94.1 | the three above on one shared base |
files | Parquet, CSV and JSON files | Apache DataFusion / Arrow / Parquet |
duckdb | DuckDB database files, :memory: and DuckLake (duckdb://) — opt-in: not in bundled, not in standard (a C++ engine, see below) | duckdb =1.10506.1 (engine 1.5.6) with bundled, Parquet and JSON; a zip stand-in (third_party/zip-stub) |
docker | docker:// URLs, \docker, container completion | bollard |
ai | ??, ???, \ai, the Python AI functions | genai, reqwest 0.13 |
explain-tui | \x plan TUI and the \sv schema browser | ratatui, textwrap |
clipboard | \ecopy | arboard |
python | PyO3 bindings (maturin passes it) | pyo3 |
# the default, everythingcargo install --path . --locked
# the slim preset: PostgreSQL, MySQL, SQLitecargo install --path . --locked --no-default-features --features standardmise run build:slim # release build of the slim presetmise run install:slim # install it
# a custom build: SQLite and ClickHouse with Docker discoverycargo build --no-default-features --features sqlite,clickhouse,docker
# the default build plus the opt-in DuckDB engine (a C++17 compiler is required)cargo install --path . --locked --features duckdb
# type-check the whole matrix (what CI does)mise run check:featuresCost of each feature, as unique crates added to the normal dependency tree (cargo tree -p dbcrust --no-default-features --features <x> -e normal), against 216 crates for the zero-engine build:
| Feature | Added crates | Feature | Added crates | |
|---|---|---|---|---|
files | +107 | ai | +34 | |
mongodb | +53 | explain-tui | +22 | |
mysql | +46 | clickhouse | +16 | |
postgres | +35 | elasticsearch | +15 | |
sqlite | +21 | redis | +12 | |
docker, clipboard | +7 each | mssql | +17 |
standard is 272 crates against 487 for bundled (redshift and libsql add no crate: they share sqlx with postgres and reqwest with the HTTP engines, see below); the dev-profile binary drops from about 327 MB (201 MB stripped) to 77 MB (49 MB stripped). DataFusion is by far the heaviest piece, which is why files is the first thing to drop.
mssql adds 7 crates to the lockfile (tiberius, tiberius-macros, asynchronous-codec, connection-string, futures-timer, pretty-hex, secrecy), roughly +1.2 MB of stripped release binary, and no C build: upstream tiberius 0.13.0 hard-codes the aws-lc-rs TLS provider (a cmake/C compile) and 0.12.3 sits on a rustls with three open RustSec advisories, so DBCrust vendors 0.13.0 with a small patch that selects ring like the rest of the tree (plus a one-line fix that lets it compile for the i686 wheels). third_party/tiberius/DBCRUST_PATCH.md records the original archive checksum, the exact diff, how to re-vendor on a release and the text of the upstream proposal; cargo tree --locked -i aws-lc-rs must keep reporting nothing.
influxdb adds no registry crate to the lockfile: the HTTP client is hand-written on the reqwest 0.12 the other HTTP drivers use, and the Flux CSV is read with csv-core, already locked through DataFusion’s csv. The influxdb crate was rejected because it wraps reqwest 0.13 with the aws-lc provider and speaks neither Flux nor v3. Its cost in the normal dependency tree is 2 crates (the driver and csv-core).
s3, dynamodb, cloudwatch (and the aws umbrella) are the opt-in AWS connectors. They are not in bundled, so release binaries, wheels and the desktop app do not contain it, and it needs Rust 1.94.1 or newer because the AWS SDK crates declare that rust-version (the workspace stays on 1.91). The new crates, dbcrust-aws (shared credentials/region/HTTP foundation), dbcrust-driver-s3, dbcrust-driver-dynamodb and dbcrust-driver-cloudwatch, declare rust-version = "1.94.1" in their own manifests; the CI job rust-aws pins that exact toolchain and checks them with the root crate. cargo install --features aws on an older compiler stops with cargo’s “requires rustc 1.94.1” message; a default build never compiles an AWS crate (CI checks cargo tree -p dbcrust for aws-*).
It adds 31 crates to the lockfile (23 aws-*/aws-smithy-*, plus base64-simd, bytes-utils, crc-fast, outref, regex-lite, urlencoding, vsimd, xmlparser) and bumps itoa, ryu and tokio-util to versions the SDK requires (34 new Cargo.lock entries in all; the normal dependency tree of bundled goes from 524 to 558 nodes, the two DBCrust crates included). Of the 34 lock entries, 29 are the shared AWS base (aws-config, the credential chain, SSO, STS and the ring HTTP client) and 5 are S3 itself (aws-sdk-s3, aws-smithy-checksums, aws-smithy-eventstream, crc-fast, the tokio-util bump); DynamoDB and CloudWatch Logs add one registry crate each on the same base (aws-sdk-dynamodb 1.130.0, aws-sdk-cloudwatchlogs 1.156.0; they share the locked aws-smithy-*, aws-types, aws-runtime, aws-smithy-eventstream and tokio-util with aws-sdk-s3, so no existing entry moved). Normal dependency tree of the bundled build (524 nodes, the DBCrust crates included): s3 → 558 (+34), dynamodb → 554 (+30), cloudwatch → 555 (+31), all three (aws) → 562 (+38: S3’s +34 and two SDK crates and two DBCrust driver crates). The dev-profile dbcrust binary goes from 338.2 MB to 360.0 MB with --features s3 (+21.7 MB), 359.1 MB with dynamodb (+20.8), 358.0 MB with cloudwatch (+19.8) and 367.3 MB with --features aws (+29.0 MB, +7.3 MB over S3 alone); after strip -x 283.7 MB → 301.2 MB (s3) and 307.1 MB (aws, +23.4 MB, +5.9 MB over S3 alone). There is no C build: everything is pure Rust, and compile time is dominated by the generated SDK crates.
TLS is rustls on ring only. The SDK’s defaults enable aws-smithy-runtime/default-https-client, which pulls aws-lc-rs (a C/cmake build); every AWS crate here is built with default-features = false, aws-smithy-http-client with its rustls-ring feature only, and dbcrust-aws builds that HTTP client and injects it into every SDK configuration. cargo tree --locked --workspace --target all -i aws-lc-rs (and aws-lc-sys, openssl, native-tls) must keep reporting nothing, with and without --features aws; CI checks it. The legacy hyper 0.14 / rustls 0.21 client (legacy-https-client) must not be enabled either. The SDK’s test-util (replay clients) is not used: it adds about fifteen test-only crates to the lockfile, so the AWS connector tests run the real SDK against an in-process HTTP server instead (S3’s REST, DynamoDB’s JSON 1.0, CloudWatch Logs’ JSON 1.1).
duckdb is the one connector that compiles a C++ engine: libduckdb-sys builds DuckDB’s amalgamation (plus the Parquet and JSON extensions, which DuckLake and the file functions need) with the cc crate, so a C++17 compiler is required. Measured on a loaded 12-core machine:
| Cold dev build of the DuckDB crates (no debuginfo) | 4 min 12 s wall, 917 s of user CPU (about 15 CPU-minutes); the figures of the release probe were 2 min 40 s wall / 18 CPU-minutes. Mr Boxington cannot cache the engine’s build script, so repeat builds in a shared target directory can redo it: use a dedicated CARGO_TARGET_DIR (the CI workflow does) |
Dev binary, standard → standard,duckdb | 58.0 MiB → 165.2 MiB unstripped (+107 MiB), 54.3 MiB → 131.1 MiB stripped (+77 MiB): the dev profile compiles the C++ unoptimised. The release probe measured +19 MB stripped (+22.5 MB with Parquet and JSON) |
| Crates in the normal tree | bundled 490 → 496 (duckdb, libduckdb-sys, dbcrust-driver-duckdb, cast, fallible-iterator, fallible-streaming-iterator); standard 272 → 300, because standard carries no Arrow |
| Lockfile | +19 registry packages: duckdb, libduckdb-sys, cast and the two fallible-*; a second crossterm (two versions: one for Windows), rustix and linux-raw-sys (through comfy-table, which duckdb enables with its terminal feature); and the build-script-only ureq, ureq-proto, utf8-zero, tar, filetime, xattr, zip, nix, typed-path, zopfli (used by the non-bundled download mode) |
Until 1.10506.1, libduckdb-sys depended on zip = "^6", whose releases are all yanked, and DBCrust patched in a stand-in crate; 1.10506.1 moved to zip 9 and the stand-in is gone. cargo tree --locked --workspace -i aws-lc-rs must keep reporting nothing with the connector in the tree, and DuckDB is excluded from the 32-bit Python check and from the release binaries and wheels (bundled does not contain it).
A disabled engine is still a DatabaseType: config files, sessions and recent.toml written by a full build keep parsing. Connecting to it fails with a message that names the feature, e.g. “MongoDB support is not compiled into this build (enable the mongodb cargo feature, or install a full build)”; dbcrust-drivers exposes is_compiled, compiled_engines and required_feature for code that has to adapt. URL-scheme completion only offers the schemes the build can serve, and the credential broker refuses to enrol an engine the build does not contain (unsupported_engine, same hint).
Adding a connector
Section titled “Adding a connector”- A
dbcrust-driver-<name>crate (depends ondbcrust-coreand its SDK only). - In
dbcrust-drivers: an optional dependency, a same-named feature, and one row in theconnectors!table ("<feature>" => Engine => path::Client;). Thematches have no wildcard, so a missing row is a compile error. - In the root
Cargo.toml:<name> = ["dbcrust-drivers/<name>"]. - Decide where it lives:
- Light (small SDK, no heavy transitive tree): add it to
bundledexplicitly, with a changelog note, so the default build gains it. - Heavy (DuckDB, AWS SDKs …): leave it out of
bundled; users opt in with--features <name>. Never add a connector tobundledsilently.
- Light (small SDK, no heavy transitive tree): add it to
- Add it to the matrix in
.github/workflows/ci.yml(rust-features) and tomise run check:features. A connector whosecargo checkis itself expensive (DuckDB compiles C++ in its build script) gets a dedicated path-filtered workflow instead of a matrix slot (.github/workflows/duckdb.yml), and stays out of the 32-bit Python check.
Testing
Section titled “Testing”mise run test # all testscargo test -- --nocapture # with stdoutcargo test test_name # specific testcargo test --lib module_name # specific modulecargo test --test "*" # integration tests onlymise run py:test # Python testsLinting and formatting
Section titled “Linting and formatting”mise run fmt # cargo fmtmise run lint # clippy (correctness, suspicious, perf as errors; style, complexity as warnings)mise run check # fmt + lint + test in sequenceBuild cache (Mr Boxington)
Section titled “Build cache (Mr Boxington)”Cargo commands run through mise — for the CLI, the desktop app and the Python bindings alike — go through Mr Boxington (mbx), the Cargo build cache by mise’s author. mise.toml installs a pinned mbx and declares a project-scoped cargo wrapper ([wrappers.cargo], mise 2026.8.16 or newer — ./bin/mise already is), so you keep typing plain cargo commands:
- Compilations are cached in one store and reused across worktrees and branches: building one checkout warms the next.
target/becomes a link to a managed directory with a disk budget; old targets and cache entries are collected automatically, and more aggressively when the disk runs low.- Builds running at the same time share one CPU and memory budget.
Cargo uses mbx when it runs through mise: mise run tasks, mise exec -- cargo …, or a shell with mise activation or shims on PATH. Check with mise exec -- mbx doctor. Editors and coding agents that call ~/.cargo/bin/cargo directly bypass the cache: point them at mise exec, and see rust-analyzer setup to route editor checks through mbx.
mise run cache:stats # savings and disk usemise run cache:gc -- --dry-run # preview what collection would reclaimmise run cache:gc # reclaim space nowCI uses the same cache through jdx/mr-boxington-action, pinned to a commit and an mbx version. Release builds don’t use it.
Rust dependency updates
Section titled “Rust dependency updates”Treat updates as code changes, not automatic trust decisions. Review upstream
release notes, repository/maintainer changes, advisories, and added transitive
crates before building. Avoid blanket cargo update; review breaking upgrades
separately. A cooldown reduces exposure to freshly published compromises but
cannot prove a package is safe.
Every new release must be at least 24 hours old, including security fixes.
Weekly Dependabot version PRs have a one-day cooldown and are not auto-merged.
Because Dependabot exempts security PRs, CI also checks every new external
Cargo.lock entry against the PR base (or the previous push), including
transitive, optional, and platform-specific dependencies. The guard verifies
crates.io publication timestamps, checksums, and yank status; missing metadata
or new non-crates.io sources fail closed. Retry a failed check after the cooldown
expires or the registry recovers. Make Rust · dependency audit a required
check in branch protection to prevent merging around it.
From the project root, using Python 3.11+ for the stdlib-only guard:
# After reviewing a specific upstream release and its publication date:cargo update -p CRATE --precise VERSIONpython3 .github/scripts/check_cargo_cooldown.py --base HEADcargo auditcargo machete --with-metadatacargo +nightly udeps --workspace --all-targets --all-features --lockedcargo test --all-features --lockedcargo clippy --all-targets --all-features --locked -- -D warningsFor committed changes use --base origin/main (fetch that ref first). Use
--locked when validating/building so Cargo cannot silently resolve newer,
unreviewed versions. Both workspace members share the root lockfile. The guard
does not replace review or constrain arbitrary local cargo update commands.
Review snapshot — 2026-11-06
Section titled “Review snapshot — 2026-11-06”cargo audit (cargo-audit 0.22.1, 1422 advisories) failed on main with
9 vulnerabilities published between 2026-10-16 and 2026-11-02, plus 12
unsoundness warnings and 2 yanked versions. Every one was fixed by a targeted
cargo update -p CRATE --precise VERSION inside the ranges the manifests already
allow. No manifest changed and no new crate entered the lockfile: there are 27
new registry versions, all of them more than 24 hours old, with matching
checksums, and none yanked.
| Crate | Old → new | Advisories fixed |
|---|---|---|
rustls-webpki | 0.103.15 → 0.103.16 | RUSTSEC-2026-0382 (distrusted emSign intermediates accepted) |
webpki-roots | 1.0.2 → 1.0.10 | RUSTSEC-2026-0381 (same emSign distrust) |
webpki-root-certs | 1.0.7 → 1.0.10 | RUSTSEC-2026-0383 (same emSign distrust; AI client’s platform verifier) |
ctutils | 0.4.2 → 0.4.4 | RUSTSEC-2026-0385 (non-constant-time masks; via digest 0.11 → hmac/sha2/pbkdf2/md-5/sha1 in MongoDB and the AWS SDK) |
zstd | 0.13.3 → 0.13.4 | RUSTSEC-2026-0391 |
zstd-safe | 7.2.4 → 7.4.0 | RUSTSEC-2026-0398, -0403; unsound -0395 to -0397, -0399 to -0402, -0404 to -0406 |
zstd-sys | 2.0.16 → 2.1.2 (zstd 1.5.7) | RUSTSEC-2026-0410 (wasm32 allocator shim) |
parquet + all 14 arrow* crates | 58.1.0 → 58.4.1 | arrow-data: RUSTSEC-2026-0442 (unsound RunEndEncoded validation) |
thrift (via parquet 58.4.1) | 0.17.0 → 0.23.0 | RUSTSEC-2026-0435 (unbounded allocation in read_bytes) |
tokio | 1.53.1 → 1.53.3 | RUSTSEC-2026-0386 (unsound AsyncFd constructors) |
async-executor | 1.14.0 → 1.14.1 | 1.14.0 yanked (GPUI / zbus stack) |
clipboard-win | 5.4.1 → 5.4.2 | 5.4.1 yanked (arboard, Windows only) |
Notes on the choices:
- Arrow/Parquet stay on 58.
parquet58.4.1 already requiresthrift0.23 andarrow58.4.1, so the fix is a minor update. The arrow crates were moved together because arrow-rs releases them in lockstep. DataFusion stays at 53.1.0 (it requires^58.0.0), and DuckDB’sarrow ^58shares the same crates. No DataFusion/Arrow major migration was needed.thrift0.23 swapsordered-float2.10.1 for 3.9.2, and it was published by the Apache Thrift release manager (Jens-G), not the 0.17 publisher. zstd-sys2.1.2, not 2.0.17. 2.0.17 has the same wasm shim fix in its source, but the advisory lists only>= 2.1.2as patched.zstd-safe7.4.0 accepts^2.0.17, so 2.1.2 fits under it. 2.1.2 ships byte-identical zstd 1.5.7 C sources and the same default build (bundled,cc, hidden symbols). Its pre-generated bindings differ only in doc comments. Its new optionalcmake/vendoredfeatures, andbindgen(no longer a default), are not enabled.zstd0.14 /zstd-safe8 would needparquet60, which no DataFusion release uses yet.- License change:
zstd0.13.4,zstd-safe7.4.0 andzstd-sys2.1.2 moved from MIT / MIT-or-Apache-2.0 to BSD-3-Clause, the bundled C library’s license. It is permissive and compatible with DBCrust’s MIT license. - Smallest patched version everywhere:
tokio1.53.3 rather than 1.54.x,ctutils0.4.4 (0.4.5 to 0.4.8 only add APIs and harden Thumb-1/RISC-V 32), andclipboard-win5.4.2 (5.4.1’s code with doc fixes; 5.4.3 changes the retry sleep). cargo tree --locked --workspace --target all -i aws-lc-rsstays empty. The ClickHouse=0.15.1pin and the vendoredtiberiusare untouched.
cargo audit passes again. The only exception is still RUSTSEC-2023-0071, and
9 informational “unmaintained” warnings remain, with no replacement crate
needed:
pin-utils(RUSTSEC-2026-0441, new on 2026-11-02) reaches the CLI throughhyper1.7.0 and the opt-in AWS connectors throughaws-smithy-http,-runtimeand-types.hyper1.9+ no longer uses it, but the AWS crates would keep it in the lockfile, so it was not bumped for this.paste(proc-macro) comes from DataFusion/parquet, genai and ClickHouse 0.15.1 (pinned; throughpolonius-the-crab→higher-kinded-types), plus the desktop app (gpui-component,metal, andimage→exr→pulp).instant,rustls-pemfile,rustybuzzandttf-parsercome only from the desktop app’s GPUI Kit stack.zvariant,zvariant_deriveandzbus_namescome from GPUI’s Linux accessibility and portal layer (accesskit→atspi,ashpd,zbus).
Review snapshot — 2026-10-17
Section titled “Review snapshot — 2026-10-17”duckdb/libduckdb-sys1.10506.1 (same DuckDB 1.5.6 engine) moved its build dependency tozip9, so the stand-inzip6.0.0 crate DBCrust had patched in is gone:cargo auditmatched it against RUSTSEC-2026-0367/0368/0369 (archive extraction in the realzip6, code the stand-in never had). The bump addszip9.0.4,nix,typed-pathandzopfli0.8.3 (build-script only,zopfliheld at 0.8.3 sobumpalo/crc32fast/simd-adler32stay put) and moveslibcto 0.2.186, the minimumnixaccepts.cargo auditpasses with 8 informational warnings, all “unmaintained”:instant,paste,rustls-pemfile,rustybuzz,ttf-parserand, new on 2026-10-16,zvariant,zvariant_deriveandzbus_names. All butpastecome only from the desktop app’s GPUI Kit stack (the last three through its Linux accessibility layer,accesskit→atspi);paste(a proc-macro) also reaches the CLI through the ClickHouse and DataFusion drivers.
Review snapshot — 2026-09-08
Section titled “Review snapshot — 2026-09-08”- Selected updates include PyO3 0.29.2 (with binding migration), Ratatui 0.30.2, usage-rs 6.8.0, MongoDB 3.9.0, DataFusion 53.1.0, and Tauri 2.11.5, plus compatible security fixes. All 160 new registry versions passed the one-day age check; none were yanked.
- Fixed 14 vulnerability findings affecting HTTP/2, Python bindings, XML,
QUIC, archive validation, TLS certificate validation, and time parsing.
Removed four unsoundness warnings and the yanked
spinversion as well. cargo auditpasses with one documented exception: RUSTSEC-2023-0071 (rsavia SQLx/MySQL). There is no patched release; this code path only encrypts credentials with a public key, not the vulnerable private-key operations. Reassess the exception when that dependency tree changes.- 20 informational warnings remain, predominantly inherited from Tauri’s
GTK3 dependencies, plus unmaintained
paste,fxhash, and Unicode helpers. These include unsoundness advisories forgliband build-timerand 0.7.3. They are not silently suppressed or claimed fixed.cargo deny checkis not a passing gate: the project has no license allowlist/deny configuration, and deny also reports the remaining advisories. - No unused direct dependencies were found by
cargo machete --with-metadataor workspace/all-featurecargo udepson macOS.prettytable-rsis used under the library nameprettytable. Platform-specific usage still needs review before any removal. - Deferred
genai 0.7.0-beta.23(published that day) and breaking updates such as SQLx 0.9, DataFusion 55, BSON 3, Reqwest 0.13, and keyring 4.
32-bit release compatibility
Section titled “32-bit release compatibility”The v0.37.1 release attempt exposed a ClickHouse 0.15.2 regression: its new
Native reader unconditionally compiles const SAFE_ALLOCATION_LIMIT: usize = 1 << 32, which overflows on i686 even though DBCrust does not use the Native
API. ClickHouse is therefore exactly pinned to 0.15.1 (published 2026-06-04,
not yanked). The remaining security updates are retained; the restored
transitive dependencies are checked by the same cooldown/audit policy.
CI now checks the actual Python extension library for
i686-unknown-linux-gnu, not just 64-bit hosts. Confirm Rust · 32-bit Python
compatibility passes before tagging a dependency release. Keep the pin until
an upstream fix passes that check; do not drop the i686 wheel to hide a failure.
To reproduce the check on an x86_64 Debian/Ubuntu development host:
sudo apt-get install gcc-multilib g++-multilibrustup target add i686-unknown-linux-gnuPYO3_NO_PYTHON=1 cargo check --locked -p dbcrust --lib --features python \ --target i686-unknown-linux-gnuPYO3_NO_PYTHON=1 uses the configured abi3-py310 ABI instead of trying to
use a 64-bit Python interpreter for the 32-bit target. This is a compile check;
the release workflow still builds and packages the real i686 wheel.
Task reference
Section titled “Task reference”All tasks are defined in mise.toml. Run mise tasks to list them.
| Task | Description |
|---|---|
build | cargo build --release |
build:dev | cargo build |
build:slim | Release build of the slim preset (--no-default-features --features standard) |
install:slim | Install the slim preset into ~/.cargo/bin |
test | cargo test |
lint | Clippy with strict settings |
fmt | cargo fmt |
check | fmt → lint → test |
check:features | cargo check of the zero-engine build, standard and each feature alone |
gui:dev | Run the desktop app (dev build, optimised dependencies) |
gui:build | Optimised build of the desktop app (target/gui-release) |
gui:install | Install dbcrust-gui into ~/.cargo/bin |
gui:bundle | macOS DBCrust.app bundle |
gui:test | Backend tests (dbcrust-gui-core) |
gui:lint | Clippy on both GUI crates |
gui:screenshots | Render docs screenshots headlessly |
gui:clean | Remove GUI build artifacts |
cache:stats | Build-cache savings and disk use (mbx stats) |
cache:gc | Reclaim build-cache disk space (mbx gc) |
py:dev | maturin develop |
py:build | maturin build --release |
py:test | python -m pytest |
all:build | Build CLI + GUI + Python |
all:clean | Clean everything |
Project layout
Section titled “Project layout”├── src/ # `dbcrust` (root crate): CLI, REPL, terminal UI, PyO3 bindings│ ├── main.rs # tokio entry point│ ├── lib.rs # public API (re-exports the crates below under their old paths) + PyO3 bindings│ ├── cli.rs # argument parsing (usage-rs derive)│ ├── cli_core.rs # REPL loop, one-shot mode and command dispatch│ ├── commands.rs # backslash command enum (strum-driven)│ ├── config_editor.rs # interactive `\config` menu + tunnel manager (schema: dbcrust-app)│ ├── terminal_ui.rs # inquire / ratatui prompts and viewers `Database` asks for│ ├── drivers.rs # facade over dbcrust-drivers│ ├── completion.rs # SQL autocompletion engine│ ├── command_completion.rs # backslash command completion│ ├── shell_completion.rs # shell completion generation (bash/zsh/fish/powershell)│ ├── prompt.rs # reedline custom prompt│ ├── highlighter.rs # SQL syntax highlighting│ ├── sql_validator.rs # reedline validator (Enter submits or continues)│ ├── sql_parser_*.rs # per-engine parsers used by completion│ ├── url_scheme.rs # URL scheme parsing and normalization│ ├── named_queries.rs # named query parameter substitution│ ├── history_manager.rs # per-session history│ ├── script.rs, pager.rs # external editor integration, output paging│ ├── logging.rs # tracing setup│ ├── update.rs # `--update`│ ├── secrets_cli/ # `dbcrust secrets` status / audit / migrate│ ├── broker/ # `dbcrust broker …` front end (prompts, arguments, e2e tests)│ ├── explain_tui/ # interactive EXPLAIN TUI (ratatui + crossterm; feature `explain-tui`)│ └── schema_tui/ # interactive schema browser TUI (feature `explain-tui`)├── crates/│ ├── core/ # dbcrust-core: client traits, model DTOs, SQL/format/display, safety, password sanitizer│ ├── app/ # dbcrust-app: config + storage, `\config` schema, `Database`, SSH/Vault/pgpass (shared by CLI and GUI)│ ├── secrets/ # dbcrust-secrets: keychain / Argon2id file store, legacy readers, config-dir/test-mode paths│ ├── drivers/ # dbcrust-drivers: engine registry, `create_database_client`, one cargo feature per engine│ ├── driver-postgres/ # one crate per engine: -mysql, -sqlite, -mongodb, -clickhouse,│ │ # -elasticsearch, -white-dragon, -files (DataFusion: Parquet/CSV/JSON)│ ├── docker/ # dbcrust-docker: daemon selection, discovery, route probing, `docker exec` relay (bollard)│ ├── ai/ # dbcrust-ai: genai assistant, agent loop, ChatGPT sign-in, `AiSession` trait│ ├── broker/ # dbcrust-broker: credential broker core (registry, admin, gateway, audit, socket server)│ ├── agent-protocol/ # wire protocol shared by the broker and the thin agent client│ └── agent/ # dbcrust-agent: credential-free client for AI coding agents├── gui/ # desktop app (GPUI Kit)│ ├── core/ # dbcrust-gui-core: workers, storage, models (no GPUI)│ ├── src/ # dbcrust-gui: views, workspace, commands│ └── ARCHITECTURE.md # module map and design language├── python/ # Python package (PyO3 + maturin)├── docs/ # MkDocs Material documentation├── mise.toml # tool + task definitions├── bin/mise # mise wrapper: runs a pinned mise without installing it (bin/mise.cmd on Windows)├── Cargo.toml # workspace root├── pyproject.toml # Python package metadata└── mkdocs.yml # docs site configArchitecture notes
Section titled “Architecture notes”- Command system: All backslash commands are variants of a
Commandenum. TheCommandShortcutenum (withstrum::EnumIter) auto-generates help text, completion, and dispatch. Never use hardcoded arrays for command lists. - Database abstraction: The
DatabaseClientandMetadataProvidertraits indatabase.rsdefine the interface. Each database has its own implementation file. - Async: Database operations use
tokio+async-trait. Shared state usesArc<Mutex<T>>. - Desktop app:
gui/core(dbcrust-gui-core) runs each connection on its own thread with a current-thread runtime +LocalSet(DBCrust futures are!Sendand sqlx pools must stay on their runtime); the GPUI views ingui/srcawait itsSendfutures. Cancellation is per request viadbcrust_core::database::set_thread_interrupt_flag. The app depends on the shared crates (dbcrust-app,dbcrust-core,dbcrust-drivers,dbcrust-docker,dbcrust-secrets), never on the CLI crate: logic both front ends need goes in those crates. - Error handling:
thiserrorfor custom error types. User-facing prompts useinquire. - Config:
serdewith#[serde(default)]for backward compatibility. Separate TOML files for settings, sessions, named queries, and recent connections.
Conventional commits
Section titled “Conventional commits”The project uses Commitizen for conventional commits:
cz commit # interactive commitcz bump # bump version based on commit history