Rust Standard

The Rust standard defines Wavenumber's first Rust profiles for host-side applications and embedded firmware. It keeps the audit boundary static: dev-std validates Cargo, rustup, repository shape, metadata, and signoff wiring while Cargo, rustc, rustfmt, Clippy, rustdoc, tests, and hardware signoff prove Rust source semantics.

Profiles

rust-app
Host-side Rust application, service, CLI, or ordinary std library with application-owned signoff.
rust-firmware
Embedded Rust firmware with no_std intent, cross-compilation, target, linker, runner, panic, allocator, and hardware signoff policy.

default_rust_app_standard

Returns the host-side Rust application and library profile.

default_rust_firmware_standard

Returns the embedded Rust firmware profile.

render_rust_app_standard

Renders the host-side Rust profile for human or machine use.

render_rust_firmware_standard

Renders the embedded Rust firmware profile for human or machine use.

Required Files

Configuration

Rust profile metadata lives under [rust]. The most common polyglot setting is source_root:

[rust]
source_root = "src/rs"

The configured path must be repository-relative, stay inside the project root, and contain at least one owned .rs file. Generated, vendored, binding, and target/ output paths are excluded from owned-source discovery.

Documented exceptions live under [rust.exceptions]. The first supported keys are ambient_toolchain for projects that follow the ambient stable Rust toolchain and unsafe for reviewed unsafe-code boundaries.

[rust.exceptions]
ambient_toolchain = "docs/design/rust-toolchain-exception.html"
unsafe = "docs/design/unsafe-boundary.html"

Cargo Metadata

Cargo.toml must define either [package] or [workspace]. Package metadata must declare edition and rust-version. Workspace member packages may inherit those fields with edition.workspace = true and rust-version.workspace = true only when [workspace.package] defines the inherited values. Workspace roots should centralize shared metadata with [workspace.package], [workspace.dependencies], [workspace.lints], and root profiles where appropriate.

Workspace member discovery follows [workspace].members and honors bounded repository-relative [workspace].exclude entries. Member globs are treated as package-directory globs; non-directory matches such as notes files under crates/ are ignored.

Workspaces must declare resolver. Edition 2024 workspaces use resolver = "3"; Edition 2021 workspaces may use resolver = "2" or "3" when the project documents the pairing.

Toolchain

rust-toolchain.toml must contain a [toolchain] table with a stable channel, rustfmt, and clippy components. Nightly, beta, or custom channels require a documented exception and review trigger. Firmware profiles must include the configured cross-compilation target unless the target is a checked-in custom target JSON file.

Unsafe Policy

Host Rust projects must set unsafe_code = "forbid" in [lints.rust] or [workspace.lints.rust]. Workspace lints are active only for packages that opt in with [lints] workspace = true; a member may also satisfy the policy with a local [lints.rust] entry, but local member overrides must still use the profile's allowed unsafe lint level. Firmware may use "forbid" or "deny" by default, or declare a documented [rust.exceptions].unsafe boundary for hardware registers, generated bindings, FFI, or reviewed low-level code. The audit validates the lint metadata and exception document; it does not scan Rust source for unsafe blocks.

Signoff Commands

Rack or an equivalent project signoff surface must expose these host Rust lanes:

Rustdoc warning failures are controlled with the RUSTDOCFLAGS environment variable, not a Cargo flag. Cargo commands should use --locked in CI and release-facing signoff so dependency resolution remains deterministic. Audit checks command markers per declared command entry; --locked on one command does not satisfy another Cargo lane. The separate cargo test --doc lane is required even when a plain cargo test lane may also run doctests, because the standard wants doctest coverage to remain visible and independently auditable when projects later add target filters.

Embedded Rust

rust-firmware adds [rust.firmware] metadata:

[rust.firmware]
target = "thumbv7em-none-eabihf"
no_std_ref = "docs/design/rust-firmware-runtime.html"
panic_ref = "docs/design/rust-firmware-runtime.html"
allocator_ref = "docs/design/rust-firmware-runtime.html"
hardware_ref = "docs/setup.html"
memory_layout = "memory.x"
runner = "Embed.toml"

The audit treats no_std as metadata and documentation. It does not inspect Rust source for #![no_std]. Firmware projects must declare the target triple or custom target spec, .cargo/config.toml, target/rustflags/runner policy, memory or linker artifacts such as memory.x or a documented link.x provider, panic strategy, allocator policy, hardware setup, flashing/debugging workflow, and host-test split.

Embedded signoff should include:

Firmware repositories that are pure no_std binaries must still provide a host-buildable crate, feature split, or wrapper surface for the host cargo test, doctest, and rustdoc lanes. Board-only code remains covered by the target build, Clippy target lane, and hardware runner.

Runtime Frameworks

Tokio is the recommended default for host-side async applications that need async I/O, networking, timers, scheduling, or service runtime facilities. Embassy is the recommended default for embedded async firmware when target and HAL support are acceptable. These are not hard dependencies in the first slice. Projects that stay synchronous, use a framework-owned runtime, use RTIC, or rely on a vendor or RTOS scheduler document the runtime choice in setup or architecture docs.

Polyglot Layouts

Contract-first repositories may keep shared schemas, fixtures, docs, and test cases at the umbrella root while language implementations live under src/<language>/. Rust model code may live under src/rs/data_models/<domain>/ or src/rust/data_models/<domain>/. Rust transforms may use operation-first roots such as src/rs/transforms/importers/<namespace>/<domain>/, src/rs/transforms/exporters/<namespace>/<domain>/, src/rs/transforms/projections/<source-domain>_to_<target-domain>/, and src/rs/transforms/migrations/<domain>/.

Generated Rust bindings or schema copies must be isolated under generated roots and governed by artifact/vendor policy instead of counted as owned implementation source.