Coding Standards
These standards apply to all code contributed to the Torvyn project. They supplement rustfmt and clippy — those tools enforce mechanical formatting and common lints. This document covers the conventions, patterns, and policies that tools cannot enforce automatically.
Rust Style
Naming Conventions
Torvyn follows standard Rust naming conventions with the following project-specific additions:
- Identity types are suffixed with
Id:ComponentId,FlowId,StreamId,ResourceId. - Configuration structs are suffixed with
Config:WasmtimeEngineConfig,FlowConfig,TierConfig. - Builder types are suffixed with
Builder:HostBuilder,PipelineTopologyBuilder. - Error types are suffixed with
Error:EngineError,FlowCreationError,LinkerError. - Trait implementations for the primary production implementation use the
Defaultprefix:DefaultResourceManager,DefaultSandboxConfigurator. This leaves the trait name clean for the abstraction.
Module Organization
Each crate follows a consistent internal structure:
src/lib.rs— Crate root. Contains#,#![deny(missing_docs)], and re-exports of the public API. No logic beyond re-exports.src/error.rsorsrc/errors.rs— All crate-specific error types, grouped in one place.- Domain modules — one file per major concept. Keep files under 500 lines when possible. If a module grows beyond 800 lines, consider splitting it.
tests/— Integration tests in the standard Cargo test directory.
Error Handling Patterns
Torvyn uses a layered error model:
- Crate-level errors (e.g.,
EngineError,LinkerError) — defined per crate usingthiserrorderives. Every variant has aDisplayimplementation that produces a complete, human-readable message. - Cross-crate error type —
TorvynErrorintorvyn-typesacts as the top-level error. Every crate-level error implementsFrom<CrateError> for TorvynError. - Error codes — Error types that correspond to user-facing diagnostics include structured error codes (e.g.,
E0100–E0199for contract errors). These codes appear in CLI output and documentation. - Never use
unwrap()orexpect()in library code. These are acceptable only in tests and in CLImain()paths where the error is immediately displayed to the user. - Use
?for propagation. Every fallible function returnsResult<T, E>whereEis either the crate-level error orTorvynError.
Documentation Standards
Every public item must have a documentation comment. The #![deny(missing_docs)] lint is enabled on all crates and enforced in CI.
Documentation comments follow this structure:
#![allow(unused)]
fn main() {
/// One-sentence summary of what this type/function does.
///
/// Longer explanation if the summary is not sufficient. Include
/// context about when and why this is used.
///
/// # Invariants (for types)
/// - List any invariants that must hold.
///
/// # Errors (for fallible functions)
/// Returns `SomeError::Variant` if the specific condition occurs.
///
/// # Panics (only if the function can panic)
/// Panics if the specific condition occurs.
///
/// # Examples
/// ```
/// // At least one runnable example for types and public functions.
/// ```
}
Performance Annotations
Torvyn uses inline comments to mark code by its performance sensitivity. This helps reviewers and future contributors understand which code is latency-critical.
// HOT PATH— Executes for every stream element. Must not allocate, must not lock, must not block. Observability overhead budget: 500ns per element at Production level.// WARM PATH— Executes per scheduling cycle or per backpressure event. Allocation is acceptable if amortized. Locks are acceptable if uncontended.// COLD PATH— Executes during startup, shutdown, or configuration changes. No performance constraints.
When adding code to a function marked HOT PATH, you must verify that your change does not introduce allocations or blocking. When in doubt, benchmark.
Test Writing Standards
Test Naming
Test names use the pattern test_<unit>_<condition>_<expected_outcome>:
#![allow(unused)]
fn main() {
#[test]
fn test_flow_state_transition_from_running_to_draining_succeeds() { ... }
#[test]
fn test_resource_id_stale_generation_returns_error() { ... }
}
Test Structure
Tests follow the Arrange-Act-Assert pattern:
#![allow(unused)]
fn main() {
#[test]
fn test_buffer_pool_allocates_from_correct_tier() {
// Arrange
let pool = BufferPoolSet::new(default_tier_config());
// Act
let handle = pool.allocate(256).unwrap();
// Assert
assert_eq!(handle.tier(), PoolTier::Small);
}
}
Coverage Expectations
There is no hard coverage percentage target, but every public function should have at least one test that exercises its happy path and one that exercises its primary error path. State machines (FlowState, ResourceState) must have tests for every valid transition and at least one test for each invalid transition.
Commit Message Format
Torvyn uses Conventional Commits. Every commit message follows this format:
<type>(<scope>): <short description>
<optional body>
<optional footer>
Types:
feat— A new feature or capabilityfix— A bug fixperf— A performance improvementrefactor— Code restructuring without behavior changetest— Adding or updating testsdocs— Documentation changeschore— Build system, CI, dependencies, or tooling changesci— CI configuration changes
Scope is the crate name without the torvyn- prefix: types, contracts, config, engine, resources, reactor, observability, security, linker, pipeline, packaging, host, cli.
Examples:
feat(reactor): add weighted fair queuing policy
fix(resources): prevent double-free on stale buffer handle
perf(engine): cache compiled components by content hash
docs(contracts): document WIT interface evolution rules
test(types): add property tests for state machine transitions
chore(deps): update wasmtime to 26.0.0
Pull Request Description Standards
Every pull request description must include:
- Summary — one or two sentences describing the change.
- Motivation — why this change is needed. Link to the issue if one exists.
- Design decisions — if the change involves a non-obvious design choice, explain it. If you considered alternatives, note them briefly.
- Testing — what tests were added or updated. How to verify the change manually if applicable.
- Performance impact — if the change touches hot-path code, describe the expected impact and any benchmark results.
Unsafe Code Policy
Unsafe code is forbidden by default. The #![forbid(unsafe_code)] attribute is set on all crates except torvyn-resources, which requires unsafe for buffer allocation and deallocation.
If you need to add unsafe code:
- Justify it. Explain in the PR description why safe alternatives are insufficient.
- Isolate it. Unsafe code must live in a dedicated module, never mixed with safe logic.
- Document every block. Every
unsafeblock must have a// SAFETY:comment that explains why the specific safety invariants are upheld. - Test the invariants. Every unsafe block must have corresponding tests that exercise the boundary conditions.
- Minimize scope. The unsafe block should contain the absolute minimum number of statements necessary.
Example of acceptable unsafe documentation:
#![allow(unused)]
fn main() {
// SAFETY: `ptr` is valid because it was allocated by `alloc::alloc` in
// `BufferPool::allocate` with a layout of `self.capacity` bytes, and
// `self.capacity` is guaranteed > 0 by the TierConfig constructor.
// The allocation has not been freed because this function holds the
// only `BufferEntry` that references it, and `BufferEntry::drop`
// is the only code path that frees it.
unsafe { std::ptr::write_bytes(ptr, 0, self.capacity) };
}
Dependency Addition Policy
Adding a new external dependency requires justification in the PR description. The following must be addressed:
- Purpose — what does this dependency provide that cannot be done with existing dependencies or standard library code?
- License — the dependency must be compatible with Apache-2.0. Acceptable licenses: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Zlib. Any other license requires explicit approval from a maintainer.
- Maintenance status — is the crate actively maintained? When was the last release? Are there open security advisories?
- Size impact — does this dependency pull in a large transitive dependency tree?
- Feature flags — enable only the features you need. Do not enable default features unless all of them are required.
Run cargo deny check (if configured) to verify license compliance before submitting.