Contributing

This guide covers everything you need to set up a bext development environment, run the test suite, and submit changes.

Prerequisites

Tool Version Notes
Rust 1.80+ (stable) Install via rustup
Bun 1.1+ Required for JS integration tests and site development
Git 2.30+
Linux Recommended Full feature testing requires kernel 5.15+ (eBPF, nsjail)

Optional (for specific features):

Tool Feature Notes
PHP 8.2+ php feature Compiled with --enable-embed --enable-zts
Redis 7+ redis feature For L2 cache and realtime relay tests
Docker Container tests For container-based integration testing
MaxMind GeoIP DB WAF geo tests GeoLite2-Country database
wasm32-wasi target WASM plugin tests rustup target add wasm32-wasi

Getting Started

git clone https://github.com/bext-dev/bext.git
cd bext

Build the community edition (fastest)

cargo build -p bext-server

Build with all features

cargo build -p bext-server --all-features

Build a release binary

cargo build --release -p bext-server

The release profile uses opt-level = 3, fat LTO, single codegen unit, and symbol stripping. Expect ~3 minutes for a full-featured release build on an M2 MacBook Pro.

Project Structure

bext/
  Cargo.toml           # Workspace root
  crates/              # Rust library and binary crates (16 crates)
  harnesses/           # Conformance, ecosystem, and security test suites
  companion/           # Desktop companion app (Tauri + Svelte)
  sites/               # bext.dev ecosystem sites (docs, blog, main, etc.)
  docs/                # Internal platform documentation

See Architecture Overview for the full crate dependency graph.

Running Tests

Unit tests (all crates)

cargo test --workspace

Unit tests for a specific crate

cargo test -p bext-core
cargo test -p bext-plugin-api
cargo test -p bext-waf
cargo test -p bext-license

Tests with all features enabled

cargo test --workspace --all-features

This is needed for WAF, plugin, eBPF, and PHP tests since those modules are behind feature flags.

Specific test

cargo test -p bext-license -- roundtrip_early_bird --nocapture

Integration tests

# Next.js conformance suite
cargo test -p conformance

# Framework ecosystem tests (requires Bun + Node)
cd harnesses/ecosystem && bun test

# Security / fuzzing harness
cargo test -p security

Plugin sandbox tests

# QuickJS plugin tests
cargo test -p bext-plugin-quickjs

# WASM plugin tests (requires wasm32-wasi target)
cargo test -p bext-plugin-wasm

# nsjail plugin tests (Linux only)
cargo test -p bext-plugin-nsjail

Code Organization

The workspace follows a strict layering discipline:

1. Leaf crates (bext-plugin-api, bext-license) have no bext dependencies and minimal external dependencies. They define traits and types. 2. Feature crates (bext-tls, bext-waf, bext-realtime, bext-ebpf, bext-php, bext-plugin-*) implement specific features. They may depend on leaf crates. 3. Core crate (bext-core) contains shared business logic. It depends on leaf crates but not on feature crates (except via Cargo features). 4. Binary crates (bext-server, bext-keygen, bext-nginx-shim) wire everything together. They depend on all other crates via feature flags.

When adding new code, place it in the lowest appropriate layer. If a type needs to be shared between feature crates, put it in bext-plugin-api or bext-core.

Code Style

- Run cargo fmt before committing.

- Run cargo clippy --workspace --all-features and fix all warnings.

- Follow existing patterns in the crate you are modifying.

- Add doc comments (/// or //!) to all new public types, functions, and modules.

- bext has 2,500+ tests -- add tests for any new functionality.

Commit Message Format

Follow conventional commits:

feat(waf): add custom rule DSL for request matching

Add a declarative rule format that lets users define WAF rules
in bext.config.toml without writing Rust code.

Closes #142

Prefixes: feat, fix, docs, refactor, test, perf, ci, chore.

The scope in parentheses should be a crate name or area (e.g., waf, cache, render, cli, docs, plugin-quickjs).

Pull Request Guidelines

1. One concern per PR -- do not mix a bug fix with a feature. 2. Add tests for any new behavior. 3. Update docs if you are changing user-facing behavior. 4. Run the full test suite before pushing: cargo test --workspace --all-features. 5. Keep PRs small -- under 500 lines changed when possible.

Checklist before submitting

- [ ] cargo test --workspace --all-features passes

- [ ] cargo clippy --workspace --all-features -- -D warnings reports no warnings

- [ ] cargo fmt --check passes

- [ ] New public types have doc comments

- [ ] Feature-gated code uses #[cfg(feature = "...")] correctly

- [ ] No new dependencies added without justification in the PR description

Review process

1. Open a PR against master. 2. CI runs the full pipeline (see below). 3. One maintainer approval required for merge. 4. Squash merge is the default. Use merge commits only for large feature branches with meaningful intermediate commits.

Adding a New Feature Flag

If your contribution adds a new optional subsystem:

1. Create the crate in crates/bext-your-feature/. 2. Add the dependency as optional in crates/bext-server/Cargo.toml:

bext-your-feature = { path = "../bext-your-feature", optional = true }

3. Define the feature in [features]:

[features]
your-feature = ["dep:bext-your-feature"]

4. Guard initialization with #[cfg(feature = "your-feature")] in main.rs and any modules that reference the crate. 5. Add a license feature name in crates/bext-license/src/tier.rs. 6. Add the feature to the appropriate tier's feature list (Community, Pro, or Enterprise). 7. Add a cargo_feature_to_license mapping. 8. Run the tier superset tests: cargo test -p bext-license.

CI Pipeline

Every PR runs:

Job What it does Duration
fmt cargo fmt --check ~5s
clippy cargo clippy --workspace --all-features -- -D warnings ~2 min
test cargo test --workspace --all-features ~4 min
build cargo build --release -p bext-server ~3 min
conformance Next.js spec tests against bext-server ~3 min
ecosystem Integration tests for Next.js, Hono, Express, Laravel, Symfony, PHP ~5 min
security Sandbox escape tests + short fuzzing run ~2 min

Release builds additionally produce binaries for Linux (x86_64, aarch64) and macOS (aarch64).

Debugging Tips

Enable trace logging

RUST_LOG=bext_server=trace,bext_core=debug cargo run

Profile a specific transform

cargo test -p bext-core transform::barrel_optimize -- --nocapture

Inspect plugin sandbox activity

BEXT_PLUGIN_LOG=trace cargo run --features plugins

Run a single conformance test

cargo test -p conformance test_name -- --nocapture

Getting Help

- Issues: github.com/bext-dev/bext/issues

- Discussions: github.com/bext-dev/bext/discussions