# Contributing to DBFlux Thanks for considering a contribution. This guide explains how to file issues, open pull requests, and follow the conventions DBFlux uses for releases and labels. ## Quick Links - [Architecture overview](ARCHITECTURE.md) - [Driver authoring guide](docs/DRIVER_AUTHORING.md) - [Release process and branching model](docs/RELEASE.md) - [Audit event schema](docs/AUDIT.md) - [Driver RPC protocol](docs/DRIVER_RPC_PROTOCOL.md) - [Lua scripting](docs/LUA.md) - [MCP / AI integration](docs/MCP_AI_INTEGRATION.md) ## Project Setup DBFlux is a Rust workspace using [GPUI](https://github.com/zed-industries/zed) for the UI. The full feature set requires the database driver feature flags: ```bash cargo check --workspace cargo build cargo run ``` On Linux, the [`mold`](https://github.com/rui314/mold) linker is **required** for local builds: `.cargo/config.toml` links the `x86_64-unknown-linux-gnu` target with `-fuse-ld=mold` to cut link time and memory across the workspace. Install it via your package manager (e.g. `apt install mold`); the Nix dev shell provides it automatically. Windows and macOS are unaffected. Before opening a PR run: ```bash python3 scripts/lint.py fmt --check python3 scripts/lint.py clippy cargo test --workspace ``` `scripts/lint.py` covers only the first-party crates under `crates/` and never lints or reformats the vendored crates under `vendor/`. Tests can also be run with [`cargo-nextest`](https://nexte.st) (faster on this workspace, provided by the Nix dev shell). Note nextest does not run doctests: ```bash cargo nextest run --workspace cargo test --doc --workspace ``` A Nix dev shell is available: `nix develop`. ## Branching Model DBFlux uses **trunk-based development with short-lived release branches**: - `main` is the only long-lived branch. All work targets `main`. - `release/vX.Y` branches are cut from `main` only when a minor needs to be stabilized for a stable release. They accept cherry-picked fixes from `main` only — no new features. Contributors should **always** target `main` with their PRs. Backporting to a release branch is a maintainer responsibility. The full rules (tags, version bumps, cut procedure, CHANGELOG discipline) live in [`docs/RELEASE.md`](docs/RELEASE.md). ## Commit Convention Use [Conventional Commits](https://www.conventionalcommits.org/) where it fits naturally: - `feat(scope): …` — new user-facing capability - `fix(scope): …` — bug fix - `refactor(scope): …` — internal change with no behavior change - `perf(scope): …` — performance improvement - `docs(scope): …` — documentation only - `test(scope): …` — tests only - `ci(scope): …` — CI / release workflow changes - `chore(scope): …` — repo plumbing (deps, tooling, version bumps) Scope is the affected area: a driver name (`postgres`, `mongodb`), `ui`, `mcp`, `audit`, `rpc`, `release`, etc. Keep the subject under 70 chars; explain the *why* in the body when non-obvious. ## Pull Requests 1. Branch from `main`. Keep PRs focused on a single concern. 2. Fill in the [PR template](.github/pull_request_template.md): summary, what it resolves, how it was solved, validation evidence, and where it was tested. 3. Link the issue it closes with `Resolves #N` in the description. 4. Apply the labels that describe the change. See [Label Guide](#label-guide) below. 5. Keep diffs reviewable. PRs over ~400 changed lines should be split into stacked/chained PRs unless the maintainer approves a `size:exception`. 6. CI must pass (`tests.yml`, `style.yml`). Re-run locally before pushing if anything fails. 7. A documentation change ships with its translations. When you edit a page under `docs/`, a driver README, or a root document the site renders (`ARCHITECTURE.md`, `CONTRIBUTING.md`, `SECURITY.md`, `TRADEMARK.md`, `PRIVACY.md`), apply the same change to every existing counterpart under `docs/es/` and `docs/zh_Hans/` in the same PR. A page with no counterpart yet needs none. See [Translations](docs/TRANSLATIONS.md). ### Commit messages and the changelog DBFlux keeps two artifacts in step from the same change: the curated `CHANGELOG.md` in this repository, and the GitHub release notes that [git-cliff](https://git-cliff.org) generates from git history in CI. Add your `## [Unreleased]` entry in the same commit as the change; the commit type decides what the generated release notes carry. Rules for what appears in the generated release notes: | Type | Surfaces in changelog? | |------|------------------------| | `feat` | Yes — under **Added** | | `fix` | Yes — under **Fixed** | | `perf` | Yes — under **Changed** | | `refactor`, `test`, `ci`, `chore`, `docs`, `style`, `build` | No — internal only | | Any type with `(security)` scope or `Security:` footer | Yes — under **Security** | Breaking changes (`feat!:`, `fix!:`, or a `BREAKING CHANGE:` footer) always surface regardless of type. **What this means in practice:** - User-visible changes **must** use `feat`, `fix`, or `perf` as the type, and add their bullet under `## [Unreleased]` (`### Added`, `### Fixed`, or `### Changed`). A `chore` or `refactor` commit is invisible to users. - Write a clear, imperative subject line — it is the bullet in the generated release notes, verbatim. - Write the `[Unreleased]` bullet for a user, not for a reviewer: it is what the repository's changelog says. - If a single PR contains both internal and user-visible changes, split them into separate commits with the appropriate types. - Security fixes: use `fix(security): ...` or add a `Security: ...` trailer so the change lands under the Security section. ## Keyboard Coverage Every action in DBFlux must be reachable from the keyboard: a command bound in the key context of the surface, or an entry of a menu the keyboard opens (the pane actions menu, or the `m` menu of a table or rail). Two checks stop a mouse-only action from landing: - `python3 scripts/lint.py mouse-down` rejects left-button `on_mouse_down` handlers that are not listed in `scripts/mouse_down_allowlist.txt`. Activations use `on_click`. - The keyboard coverage tests render each surface and check every element that runs an action on click against the coverage registry of that surface (`dbflux_ui_base::keyboard_coverage`). An element the registry does not list fails the test, and the failure says how to fix it. When you add an interactive element: 1. Give it a stable `.id(...)` and activate it with `.on_click(...)`. 2. Give its action a keyboard path: a `Command` bound in the key context of the surface, or an entry in its pane actions or `m` menu that runs the same action. Inside a dialog, a control that takes focus is reached with Tab. 3. Register the id in the registry of the surface that draws it: `crates/dbflux_ui_document/src/keyboard_coverage.rs` for documents, `crates/dbflux_ui_windows/src/keyboard_coverage.rs` for the settings and connection manager windows, `crates/dbflux_ui/src/ui/views/workspace/keyboard_coverage_tests.rs` for the workspace shell, or the test module of a dialog. Use `KeyboardPath::MouseOnly("reason")` only for window chrome and pointer gestures. A reason that starts with `gap:` records a missing keyboard path so it stays visible. Run the coverage tests with: ```bash cargo nextest run --workspace _covered ``` A workspace run builds the UI crates with the features the app ships with, so it also checks the MCP surfaces and the Lua hook mode. The helper's own tests run with `cargo nextest run -p dbflux_ui_base keyboard_coverage`. ## Issues Before opening an issue: - Search existing issues to avoid duplicates. - Reproduce against a recent build if you can. Include: - Version of DBFlux (`dbflux --version`), OS / display server (X11 vs Wayland on Linux), and database engine + version. - Steps to reproduce. - Expected vs actual behavior. - Logs if relevant. Redact secrets. Apply the labels that describe the issue. See [Label Guide](#label-guide). ## Label Guide The repo uses a structured label taxonomy. Apply **one label from each applicable axis** when opening an issue or PR. Maintainers may adjust during triage. ### Kind (one of `*:bug` or `*:feature` per affected area) Areas that have a bug/feature split: | Area | Bug | Feature | |-----------|--------------------|----------------------| | AWS | `aws:bug` | `aws:feature` | | Audit | `audit:bug` | `audit:feature` | | Driver | `driver:bug` | `driver:feature` | | MCP | `mcp:bug` | `mcp:feature` | | Pipeline | `pipeline:bug` | `pipeline:feature` | | Proxy | `proxy:bug` | `proxy:feature` | | Query | `query:bug` | `query:feature` | | RPC | `rpc:bug` | `rpc:feature` | | SSH | `ssh:bug` | `ssh:feature` | | Storage | `storage:bug` | `storage:feature` | | UI | `ui:bug` | `ui:feature` | Plus the generic GitHub-default `bug`, `documentation`, `question`, `help wanted`, `good first issue`, `invalid`. ### Subsystem flags (apply when relevant) - `aws`, `proxy`, `ssh`, `query`, `driver`, `mcp` ### Driver (when the change is driver-specific) `driver:mongodb`, `driver:postgres`, `driver:sqlite`, `driver:mysql/mariadb`, `driver:dynamodb`, `driver:redis` ### Data model kind (for store/driver-level work) `kind:sql`, `kind:document`, `kind:kv`, `kind:log` ### Platform / Arch (when behavior is platform-specific) - Platform: `platform:linux`, `platform:macos`, `platform:windows` - Arch: `arch:amd64`, `arch:arm64` ### RPC subtype (when touching RPC-backed services) `rpc:auth`, `rpc:driver` (in addition to `rpc:bug`/`rpc:feature`) ### Priority `priority:high`, `priority:medium`, `priority:low` — usually applied by maintainers during triage. ### Status (applied by maintainers) `status:needs-review`, `status:approved`, `status:rejected` ### Example combinations - A PostgreSQL JSON query bug on Linux: `driver:bug`, `driver:postgres`, `query:bug`, `platform:linux`, `kind:sql` - A new Redis pub/sub feature: `driver:feature`, `driver:redis`, `kind:kv` - An MCP approval-flow regression on Windows: `mcp:bug`, `platform:windows` - An SSH tunnel UI improvement: `ui:feature`, `ssh:feature`, `ssh` If you're unsure, label as best you can — maintainers will refine during triage. ## Security Do not file security issues publicly. Email the maintainer or use a private channel. Logs and reproductions must be redacted of secrets (tokens, passwords, connection strings). ## License By contributing you agree your contributions are licensed under the project's dual MIT / Apache-2.0 license. The DBFlux name and logo are not part of that license; see [TRADEMARK.md](TRADEMARK.md).