Thank you for your interest in contributing to PJS (Priority JSON Streaming Protocol). This document provides guidelines and instructions for contributing to the project.
- Code of Conduct
- Getting Started
- Development Workflow
- Testing Requirements
- Code Quality Standards
- Pull Request Process
- Project Architecture
- Feature Flags
- Cross-Platform Considerations
This project adheres to the Rust Project Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers. See CODE_OF_CONDUCT.md for details.
PJS requires nightly Rust 1.89+ for Generic Associated Types (GAT) features:
# Install nightly Rust
rustup install nightly
# Set nightly as override for this project
cd pjs
rustup override set nightly
# Verify nightly is active
rustc --version # Should show "nightly"# Clone the repository
git clone https://github.com/bug-ops/pjs.git
cd pjs
# Build the project
cargo build
# Run tests to verify setup
cargo nextest run --workspace# cargo-nextest for faster test execution
cargo install cargo-nextest
# cargo-llvm-cov for code coverage
cargo install cargo-llvm-cov
# wasm-pack for WebAssembly builds (optional)
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | shUse descriptive branch names following this pattern:
feat/description- New featuresfix/description- Bug fixesrefactor/description- Code refactoringdocs/description- Documentation changeschore/description- Maintenance taskstest/description- Test improvementsperf/description- Performance improvements
Examples:
git checkout -b feat/add-custom-priority-strategy
git checkout -b fix/windows-instant-overflow
git checkout -b refactor/gat-migrationWrite clear, descriptive commit messages:
Format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat- New featurefix- Bug fixrefactor- Code refactoringdocs- Documentation changestest- Test improvementsperf- Performance improvementschore- Maintenance tasksci- CI/CD changes
Examples:
feat(parser): add SIMD-accelerated JSON parsing
Implement AVX2-optimized parsing for 6x performance gain on large payloads.
Uses sonic-rs backend with zero-copy operations.
Closes #123
fix(metrics): prevent Windows Instant overflow in time series
Use checked_sub() to handle duration calculation when cutoff exceeds
program uptime. Fixes panic on Windows in metrics collector.
Fixes #456
Important: Keep commit messages concise and professional. Do not use emojis or informal language.
PJS uses cargo-nextest for test execution:
# Run all tests
cargo nextest run --workspace
# Run tests with all features
cargo nextest run --workspace --all-features
# Run tests for specific crate
cargo nextest run -p pjson-rs
cargo nextest run -p pjson-rs-domain
cargo nextest run -p pjs-wasm
# Run specific test by name
cargo nextest run test_schema_validation
# Run tests with output visible
cargo nextest run --nocapture
# Run doctests
cargo test --workspace --docAll contributions must maintain or improve code coverage:
# Generate coverage report with HTML output
cargo llvm-cov nextest --workspace --all-features --html
open target/llvm-cov/html/index.html
# Generate coverage for specific crate
cargo llvm-cov nextest -p pjson-rs --html
# Check coverage summary
cargo llvm-cov nextest --workspace --summary-onlyCoverage Requirements:
- Domain Layer (
pjson-rs-domain): Minimum 80% coverage (enforced in CI) - Core Library (
pjson-rs): Minimum 70% coverage (recommended) - Infrastructure Layer: Minimum 60% coverage (recommended)
- Security-Critical Code: 100% coverage required
security/module (rate limiting, compression bomb detection)domain/services/validation_service.rsparser/security checks
Coverage Quality Guidelines:
- All public APIs must have test coverage
- Error paths must be tested
- Edge cases and boundary conditions required
- Security-critical code requires comprehensive tests
- Zero unsafe code without 100% test coverage
Unit Tests:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_priority_ordering() {
let high = Priority::new(90).unwrap();
let low = Priority::new(10).unwrap();
assert!(high > low);
}
}Integration Tests:
// In crates/pjs-core/tests/
#[tokio::test]
async fn test_session_lifecycle() {
let service = SessionService::new(/* deps */);
let session_id = service.create_session().await.unwrap();
assert!(service.get_session(&session_id).await.is_ok());
}Property-Based Tests:
use proptest::prelude::*;
proptest! {
#[test]
fn priority_values_are_valid(p in 0u8..=100) {
let priority = Priority::new(p);
assert!(priority.is_ok());
}
}All code must pass strict quality checks before merging:
# Check formatting (required before commit)
cargo +nightly fmt --all --check
# Auto-format code
cargo +nightly fmt --all# Run clippy in strict mode (zero warnings allowed)
cargo clippy --workspace --all-features --all-targets -- -D warningsImportant: All clippy warnings must be resolved. The CI enforces -D warnings (deny warnings).
Before committing, run:
# 1. Format code
cargo +nightly fmt --all
# 2. Check for clippy warnings
cargo clippy --workspace --all-features --all-targets -- -D warnings
# 3. Run all tests
cargo nextest run --workspace --all-features
# 4. Verify doctests
cargo test --workspace --doc
# 5. Check coverage (optional but recommended)
cargo llvm-cov nextest --workspace --summary-only-
Ensure your branch is up to date with
main:git fetch origin git rebase origin/main
-
Run the full CI check locally:
cargo +nightly fmt --all --check cargo clippy --workspace --all-features -- -D warnings cargo nextest run --workspace --all-features cargo test --workspace --doc -
Update documentation if needed:
- Update
CHANGELOG.mdwith your changes - Update README.md if adding new features
- Add/update code examples
- Update architecture documentation if changing structure
- Update
Title Format:
<type>(<scope>): <description>
Description Template:
## Summary
Brief description of what this PR does and why.
## Changes
- Change 1
- Change 2
- Change 3
## Testing
Describe how you tested these changes:
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed
- [ ] Coverage maintained/improved
## Checklist
- [ ] Code follows project style guidelines
- [ ] Tests pass locally
- [ ] Coverage requirements met
- [ ] Documentation updated
- [ ] CHANGELOG.md updated
- [ ] No clippy warnings
- [ ] Formatted with `cargo +nightly fmt`
## Related Issues
Closes #123-
Automated Checks: CI must pass before review
- Code quality (formatting, clippy)
- Tests (all platforms: Linux, macOS, Windows)
- Coverage thresholds
- Security scanning (OSV)
- WASM builds (if applicable)
-
Code Review: At least one maintainer approval required
- Architecture compliance
- Code quality and readability
- Test coverage
- Documentation completeness
-
Merge: Squash and merge to
mainafter approval
PJS follows Clean Architecture with Domain-Driven Design. Understanding this is crucial for contributions:
crates/
├── pjs-domain/ # Pure business logic (WASM-compatible)
│ ├── value_objects/ # Priority, SessionId, Schema, JsonData
│ ├── entities/ # StreamSession, Stream
│ ├── events/ # Domain events
│ └── ports/ # GAT-based traits
├── pjs-core/ # Rust implementation
│ ├── application/ # CQRS handlers, use cases
│ ├── infrastructure/ # HTTP, WebSocket, repositories
│ ├── parser/ # SIMD JSON parsing
│ └── stream/ # Priority streaming engine
├── pjs-wasm/ # WebAssembly bindings
├── pjs-bench/ # Performance benchmarks
└── pjs-demo/ # Demo applications
- Domain Layer must not depend on infrastructure or application layers
- Domain Layer must not import
serde_json::Value(useJsonDatainstead) - Application Layer orchestrates but contains no business logic
- Infrastructure Layer implements domain ports (traits)
- All async abstractions use GATs (Generic Associated Types), not
async_trait
Example: Adding a new validation rule
- Update domain value object:
domain/value_objects/schema.rs - Implement validation logic:
domain/services/validation_service.rs - Add DTOs:
application/dto/schema_dto.rs - Add integration tests:
crates/pjs-core/tests/ - Add benchmarks:
crates/pjs-bench/benches/
PJS uses feature flags to minimize compile times and binary size. Be mindful when adding dependencies:
simd-auto- Auto-detect SIMD supportschema-validation- Schema validation engine
compression- Schema-based compressionhttp-server- Axum HTTP serverwebsocket-client- WebSocket clientwebsocket-server- WebSocket serverhttp-client- HTTP event publishing
jemalloc- Use jemalloc allocatormimalloc- Use mimalloc allocator
-
Add feature to
Cargo.toml:[features] my-feature = ["dep:some-crate"]
-
Gate code with feature flag:
#[cfg(feature = "my-feature")] pub mod my_feature { // Feature-specific code }
-
Update CI to test with new feature:
# .github/workflows/ci.yml - run: cargo test --features my-feature
-
Document in README.md feature table
PJS supports Linux, macOS, and Windows. All contributions must work on all platforms.
Use conditional compilation when necessary:
#[cfg(target_os = "windows")]
fn platform_specific() {
// Windows implementation
}
#[cfg(not(target_os = "windows"))]
fn platform_specific() {
// Unix implementation
}Windows:
- Time precision: Use
checked_sub()forInstantcalculations - Path separators: Use
std::path::PathBuf - Line endings: Git handles CRLF/LF automatically
macOS:
- File system is case-insensitive by default
- Test on both Intel and Apple Silicon if possible
Linux:
- Default CI platform
- jemalloc works best here
If you can't test on all platforms, CI will catch issues, but try to consider:
# Run platform-specific tests
cargo nextest run --workspace --all-features
# Check for platform-specific warnings
cargo clippy --target x86_64-pc-windows-msvc
cargo clippy --target x86_64-apple-darwin
cargo clippy --target x86_64-unknown-linux-gnuWhen making performance-related changes, always benchmark:
# Save baseline before changes
cargo bench -p pjs-bench -- --save-baseline before
# Make your changes
# Compare against baseline
cargo bench -p pjs-bench -- --baseline before
# View results
open target/criterion/report/index.htmlBenchmark Suites:
simple_throughput.rs- Parser performancememory_benchmarks.rs- Arena allocation efficiencystreaming_benchmarks.rs- Progressive loading speed
Use clear, concise doc comments:
/// Parses JSON with priority-based frame generation.
///
/// # Arguments
///
/// * `json` - Input JSON string
/// * `min_priority` - Minimum priority threshold (0-100)
///
/// # Returns
///
/// Vector of frames ordered by priority
///
/// # Example
///
/// ```
/// use pjson_rs::parser::parse;
/// let frames = parse(r#"{"id": 123}"#, 50);
/// ```
///
/// # Errors
///
/// Returns `ParseError` if JSON is invalid
pub fn parse(json: &str, min_priority: u8) -> Result<Vec<Frame>, ParseError> {
// ...
}Update relevant docs when changing architecture:
docs/architecture/SPECIFICATION.md- Protocol specificationCLAUDE.md- Project instructions for AI assistants.local/- Internal project documentation
- GitHub Discussions: https://github.com/bug-ops/pjs/discussions
- Issues: https://github.com/bug-ops/pjs/issues
- Documentation: https://docs.rs/pjson-rs
By contributing to PJS, you agree that your contributions will be licensed under both the MIT License and Apache License 2.0, at the user's option.