104 lines
6.9 KiB
Markdown
104 lines
6.9 KiB
Markdown
# Project Standards: Code & Documentation
|
|
|
|
This document defines the absolute highest standards for the development of the Voice App project. All contributors must adhere to these rules strictly to ensure maximum performance, security, and maintainability.
|
|
|
|
## 1. Rust Coding Standards
|
|
|
|
### 1.1 Strict Linting & Safety
|
|
The project enforces strict, zero-tolerance compiler checks. Every crate must begin with (or include in `Cargo.toml` as workspace lints):
|
|
|
|
```rust
|
|
#![forbid(unsafe_code)]
|
|
#![deny(clippy::all, clippy::pedantic)]
|
|
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
|
```
|
|
* **Unsafe Code:** Completely banned. If a dependency requires `unsafe`, it must be highly audited and isolated.
|
|
* **No Unwraps:** `unwrap()` and `expect()` are forbidden in production code. You must handle the `Result` or `Option` gracefully and bubble it up using the `?` operator.
|
|
|
|
### 1.2 Error Handling
|
|
* **Libraries (`core_protocol`):** Must define their own custom error enumerations using `thiserror`. Do not panic.
|
|
* **Binaries (`client_node`, `server_node`):** Use `anyhow::Result` for application-level error bubbling. All bubbled errors must be logged using `tracing::error!` before the process safely terminates or restarts the specific actor.
|
|
|
|
### 1.3 Concurrency & The Actor Pattern
|
|
* **No Shared Mutexes for Data Flow:** Passing an `Arc<Mutex<State>>` directly between the Tokio network background thread and the `egui` UI thread is prohibited, as it causes stuttering.
|
|
* **Enforce the Actor Pattern:** Use `tokio::sync::mpsc` (UI -> Network) and `tokio::sync::watch` (Network -> UI) for all cross-thread communication.
|
|
* **Blocking Operations:** Database queries (`sqlx` is async so it's fine), heavy cryptography (e.g., Argon2 hashing), or file I/O must *never* run on the main Tokio executor thread. They must be offloaded using `tokio::task::spawn_blocking`.
|
|
|
|
### 1.4 High-Performance Audio Rules
|
|
* **Lock-Free Audio Threads:** The `cpal` audio input and output callbacks operate in real-time. You are strictly forbidden from placing `Mutex::lock()`, network socket calls, or heap memory allocations (`Vec::new()`, `String::from()`) inside the audio callback.
|
|
* **Zero-Copy Routing:** The Server's UDP relay must utilize the `bytes::Bytes` crate to share network packet payloads via reference counting. It must never clone raw arrays when broadcasting to multiple users in a channel.
|
|
|
|
---
|
|
|
|
## 2. Documentation Standards
|
|
|
|
### 2.1 The "Why", Not the "What"
|
|
Code should be readable enough to explain *what* it is doing. Inline comments must explain *why* a specific decision was made (e.g., "We pad this buffer to 960 samples because Opus strictly requires a 20ms mathematical frame, otherwise it throws an invalid packet error.").
|
|
|
|
### 2.2 Docstrings
|
|
Every public `struct`, `enum`, `fn`, and `mod` must have a standard `///` docstring.
|
|
Functions returning a `Result` must include an `# Errors` section.
|
|
|
|
```rust
|
|
/// Encodes raw f32 audio samples into a compressed Opus frame.
|
|
///
|
|
/// # Arguments
|
|
/// * `pcm_data` - A slice of exactly 960 audio samples representing 20ms of audio.
|
|
///
|
|
/// # Errors
|
|
/// Returns `AudioError::InvalidFrameSize` if the length of `pcm_data` is not exactly 960.
|
|
pub fn encode_frame(pcm_data: &[f32]) -> Result<Vec<u8>, AudioError> { ... }
|
|
```
|
|
|
|
### 2.3 Module Level Documentation
|
|
Every `lib.rs` or `mod.rs` file must begin with a `//!` documentation block explaining the architectural purpose of that module. If a developer opens a file, the first paragraph should tell them exactly what the module's responsibility is.
|
|
|
|
### 2.4 Architecture Decision Records (ADRs)
|
|
If you propose a fundamental change to the architecture (e.g., changing the database from SQLite to PostgreSQL, or swapping Extism for Wasmtime), it must first be documented in a new file under `Documentation/ADR/` detailing the Context, Decision, and Consequences.
|
|
|
|
---
|
|
|
|
## 3. Security Standards
|
|
|
|
* **Zero-Knowledge Logging:** Never log passwords, Argon2 hashes, raw JWT tokens, or UDP Session Tokens via the `tracing` framework. Use `[REDACTED]` if you must log an event involving secure data.
|
|
* **Memory Sanitization:** Highly sensitive cryptographic material in memory should utilize the `secrecy` crate to ensure it is Zeroized (wiped from RAM) the moment it falls out of scope.
|
|
* **Strict API Validation:** Never trust the client. The server must validate the lengths, bounds, and permissions of every single TCP event and UDP packet before processing it.
|
|
|
|
---
|
|
|
|
## 4. Git & Workflow Standards
|
|
|
|
* **Conventional Commits:** Commit messages must follow the standard:
|
|
* `feat: added global hotkeys for PTT`
|
|
* `fix: resolved Opus frame alignment crash`
|
|
* `refactor: migrated UDP payload to bytes crate`
|
|
* `docs: updated API documentation for Wasm plugin`
|
|
* **CI/CD Constraints:** No code is merged into `main` unless it successfully passes:
|
|
1. `cargo fmt --all -- --check`
|
|
2. `cargo clippy --all-targets --all-features -- -D warnings`
|
|
3. `cargo test --all`
|
|
|
|
---
|
|
|
|
## 5. Testing & Quality Assurance
|
|
|
|
* **Property-Based Testing:** Network boundaries (especially the UDP parser) must use property-based testing (e.g., the `proptest` crate) to throw random, garbage bytes at the decoders. A malformed network packet must never cause the server or client to panic.
|
|
* **Mocking Hardware Interfaces:** To ensure the CI pipeline can run headless without physical microphones, the audio capture interface (`cpal`) must be abstracted. The test suite will feed deterministic "sine wave" `f32` vectors into the DSP pipeline to mathematically verify encoding/decoding.
|
|
* **Unit Testing Core Logic:** All state transitions, RBAC permissions, and packet serializers must have 100% test coverage.
|
|
|
|
---
|
|
|
|
## 6. Cross-Platform Constraints
|
|
|
|
* **Strict OS Agnosticism:** Core business logic must remain OS-agnostic. Any OS-specific system calls (like Windows Registry Hooks or Linux `alsa` tweaks) must be isolated behind `#[cfg(target_os = "...")]` compilation flags.
|
|
* **Fallback Mandate:** If an OS-specific feature is added (e.g., a Windows global hotkey), a functional equivalent or safe fallback must be provided for Linux and macOS in the exact same Pull Request.
|
|
* **Pathing:** Hardcoding `/` or `\` in strings is forbidden. Developers must strictly use `std::path::PathBuf` for all file system interactions to ensure Windows/POSIX compatibility.
|
|
|
|
---
|
|
|
|
## 7. Dependency Management & Telemetry
|
|
|
|
* **Dependency Minimalism:** Before adding a new crate to `Cargo.toml`, evaluate if the feature can be implemented natively in under 100 lines of Rust. Heavy, sprawling dependencies will be rejected.
|
|
* **Security Auditing:** `cargo audit` must be integrated into the CI pipeline to automatically fail builds if a known CVE is discovered in the dependency tree.
|
|
* **Server Telemetry:** Beyond text logs, the server must expose a `/metrics` Prometheus endpoint to track high-level health metrics: concurrent active users, UDP packet drop rate, Jitter buffer latency spikes, and CPU/Memory usage.
|