Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/docs-site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Deploy Docs

on:
push:
branches:
- main
paths:
- 'docs/**'
- '.github/workflows/docs-site.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
mdbook-deploy:
name: Build and deploy mdBook
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4

- name: Install mdbook
uses: peaceiris/actions-mdbook@v2
with:
mdbook-version: 'latest'

- name: Install mdbook-mermaid
run: |
cargo install mdbook-mermaid

- name: Build docs
run: mdbook build docs/

- name: Setup Pages
uses: actions/configure-pages@v5

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/book

- id: deployment
name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
/target/
tests/node/node_modules/
.sisyphus
.sisyphus/
.vogon_poetry/
docs/book/

# Task artifacts — planning docs, Ralph Loop prompts, progress trackers, PR checklists.
# These should never land in git. If you need to commit one, do it explicitly and it
# will still be surfaced by the pre-PR artifact scan described in AGENTS.md.
DOCS_PLAN.md
RALPH_PROMPT.md
REFACTOR_PLAN.md
PR-TODOS.md
*_PLAN.md
*_PROMPT.md
*_TODOS.md
109 changes: 109 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# AGENTS.md — peeroxide workspace root

This is the root of the peeroxide workspace — a Rust implementation of the Hyperswarm P2P networking stack, wire-compatible with the Node.js reference implementation.

## Workspace Crates

| Crate | Description | Published |
|---|---|---|
| `peeroxide` | High-level swarm management and topic-based peer discovery | crates.io |
| `peeroxide-dht` | HyperDHT: Kademlia routing, Noise handshakes, hole-punching, relay | crates.io |
| `libudx` | UDX reliable UDP transport with BBR congestion control | crates.io |
| `peeroxide-cli` | CLI toolkit: lookup, announce, ping, cp, deaddrop | binary only |

The three library crates are published to crates.io and have external users. `peeroxide-cli` is a consumer of those libraries, not a library itself.

## Key Files

- `docs/` — mdBook documentation source (build: `mdbook build docs/`)
- `.github/workflows/` — CI (`ci.yml`), release (`release.yml`), docs (`docs-site.yml`)

## Build

```bash
# Build all crates
cargo build --workspace

# Run all tests (unit + integration + Node.js interop)
cargo test --workspace

# Run live network tests (requires internet — public HyperDHT bootstrap nodes)
cargo test -p peeroxide-cli --test live_commands -- --ignored

# Build documentation site
mdbook build docs/
```

## Architecture

```
peeroxide — topic-based peer discovery + connection management
└── peeroxide-dht — Kademlia DHT, Noise handshakes, hole-punching, relay
└── libudx — reliable UDP transport with BBR congestion control
```

## API Breaking Change Policy — HARD STOP

**Any change that modifies or removes an existing public API in `libudx`, `peeroxide-dht`, or `peeroxide` is a breaking change. You must stop and get explicit human approval before making one. No exceptions.**

### What counts as breaking

- Changing a function/method signature (parameter types, return type, receiver type)
- Removing a public function, method, field, or type
- Changing a public field's type
- Adding a required parameter to an existing function

### What does NOT count as breaking

- Adding new public functions, methods, or types
- Adding optional parameters via a new companion function
- Internal implementation changes with no public surface effect

### The boundary that matters

`peeroxide-cli` is a binary consumer. Constraints it places on how it uses library internals (e.g. needing to share a socket across tasks) must be solved **inside `peeroxide-cli` or by adding new non-breaking API**, never by altering existing library signatures.

If you find yourself needing to change a library signature to satisfy a CLI feature, stop. Propose an additive solution (new method, wrapper type, trait impl) and wait for approval.

### What to do when you hit this wall

1. Stop. Do not implement the breaking change.
2. Document the constraint you encountered and why it creates pressure toward a break.
3. List at least two non-breaking alternatives (e.g. new method, wrapper type, `Arc` inside the type).
4. Ask the human which approach to take.

## Test Completeness

"All tests pass" means all three suites:

1. `cargo test --workspace` — unit tests, integration tests, and the Node.js local interop test (`hyperswarm_cross_language_connect`)
2. `cargo test -p peeroxide-cli --test live_commands -- --ignored` — live public HyperDHT network tests (lookup, announce, cp, deaddrop)

Do not mark work complete until both suites are green.

## Task Artifacts

Task-specific files (planning docs, progress trackers, spec drafts, Ralph Loop prompts, PR checklists, etc.) must **not** be committed to git unless explicitly directed by the human.

Before opening or merging a PR, scan the branch's added files (`git diff --name-only --diff-filter=A main`) and flag any task-artifact files to the human. Examples of files that should not be in git:

- `*_PLAN.md`, `*_PROMPT.md`, `*_TODOS.md`
- `DOCS_PLAN.md`, `RALPH_PROMPT.md`, `PR-TODOS.md`
- Any per-task progress trackers or scratch notes

If such a file appears, verify with the human that its inclusion is intentional before committing or pushing.

## Agent Notes

- Do not push to remote — commits are local until explicitly requested.
- MSRV: Rust 1.85 (2024 edition).

## PR Checklist

The full checklist is in [CONTRIBUTING.md](./CONTRIBUTING.md). **Check it before opening a PR or merging.** Key gates:

- Both test suites green (see Test Completeness above)
- Clippy clean
- No API breaking changes without explicit human approval
- No task-artifact files in the branch (see Task Artifacts above)
- CI green before merge
80 changes: 6 additions & 74 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,78 +1,10 @@
# Changelog

All notable changes to this project will be documented in this file.
This workspace contains multiple crates, each with its own changelog:

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- [peeroxide](./peeroxide/CHANGELOG.md)
- [peeroxide-dht](./peeroxide-dht/CHANGELOG.md)
- [libudx](./libudx/CHANGELOG.md)
- [peeroxide-cli](./peeroxide-cli/CHANGELOG.md)

## [1.0.0] - 2025-04-25

Initial release. Pure Rust implementation of the Hyperswarm P2P networking
stack, wire-compatible with the existing Node.js network.

### Added

#### peeroxide

- Topic-based peer discovery and connection management (Hyperswarm port)
- `SwarmConfig` with configurable max peers, firewall callback, backoff, and jitter
- `spawn()` returns `(JoinHandle, SwarmHandle, Receiver<SwarmConnection>)`
- `SwarmHandle`: `join()`, `leave()`, `status()`, `destroy()`
- Connection deduplication by remote public key
- Peer state machine with priority scoring and exponential retry backoff
- `SwarmConfig::with_public_bootstrap()` for connecting to the live HyperDHT network
- `discovery_key()` helper for topic hashing

#### peeroxide-dht

- Full HyperDHT implementation (Kademlia DHT, hole-punching, blind relay)
- Noise XX and Noise IK handshake patterns (Ed25519 DH, ChaChaPoly)
- SecretStream transport (pure-Rust libsodium `crypto_secretstream_xchacha20poly1305`)
- Protomux channel multiplexer (actor model, ~1460 lines)
- Blind relay client for NAT traversal
- Compact encoding (all types from the Node.js `compact-encoding` package)
- Server-side record storage with LRU+TTL eviction
- `HyperDhtHandle` client API: `lookup`, `announce`, `find_peer`, `unannounce`, `immutable_put/get`, `mutable_put/get`, `connect`, `register_server`
- NAT classification (OPEN/CONSISTENT/RANDOM/UNKNOWN)
- Socket pool with multi-socket management
- Holepunch strategy selection (direct, birthday paradox)
- Async DNS resolution for bootstrap nodes
- `HyperDhtConfig::with_public_bootstrap()` for live network use

#### libudx

- Pure Rust UDX protocol implementation (replaced C FFI bindings)
- BBR congestion control (faithful port of C `udx_bbr.c`)
- Reliability: cumulative ACK, SACK, retransmission with RTO, fast retransmit
- RTT estimation (Jacobson/Karels per RFC 6298)
- Rate sampling for BBR bandwidth estimation
- Token bucket pacing
- MTU probing (base 1200, max 1500, step 32)
- Relay packet forwarding (header rewriting, DESTROY propagation)
- `UdxAsyncStream`: `AsyncRead + AsyncWrite + Unpin` adapter for tokio
- Multiplexing: multiple streams per socket with independent congestion state
- Heartbeat keepalive (1s interval)
- Graceful shutdown with buffered write drain

### Tested

- 497 tests passing (0 failed, 6 ignored)
- Golden byte fixtures verified against Node.js reference implementations
- Live cross-language interop tests (Rust <-> Node.js) at every protocol layer
- Network simulation tests with configurable loss, delay, jitter, reorder, and MTU clamping
- Public HyperDHT bootstrap + announce/lookup smoke tests (ignored by default)

### Dependencies

- Pure Rust crypto stack (RustCrypto: blake2, ed25519-dalek, curve25519-dalek,
sha2, chacha20poly1305, xsalsa20poly1305, hmac, poly1305)
- tokio async runtime
- No C dependencies

### Compatibility

- Wire-compatible with Node.js Hyperswarm, HyperDHT, and libudx
- Rust edition 2024, MSRV 1.85
- Dual-licensed: MIT OR Apache-2.0

[1.0.0]: https://github.com/Rightbracket/peeroxide/releases/tag/v1.0.0
Releases are managed automatically via [release-plz](https://release-plz.ieni.dev/).
93 changes: 49 additions & 44 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,78 +1,83 @@
# Contributing to Peeroxide

Thank you for your interest in contributing to Peeroxide. This project is a Rust implementation of the Hyperswarm stack, focusing on wire compatibility with the Node.js reference network.
This project is a Rust implementation of the Hyperswarm stack, focusing on wire compatibility with the Node.js reference network.

## Crate Stack

The workspace consists of three primary crates:
1. **libudx**: Reliable UDP transport with BBR congestion control.
2. **peeroxide-dht**: Kademlia DHT, Noise handshakes, hole-punching, and relaying.
3. **peeroxide**: High-level swarm and topic-based discovery.
| Crate | Description | Published |
|---|---|---|
| `libudx` | Reliable UDP transport with BBR congestion control | crates.io |
| `peeroxide-dht` | Kademlia DHT, Noise handshakes, hole-punching, relay | crates.io |
| `peeroxide` | High-level swarm and topic-based discovery | crates.io |
| `peeroxide-cli` | CLI toolkit: lookup, announce, ping, cp, deaddrop | crates.io (binary) |

## Development Requirements

- **Rust 2024 edition** (MSRV 1.85)
- **Node.js 18+** and **npm 9+** (required for interop tests)
- **Docker** (optional, for NAT simulation tests)
- **Node.js 20+** and **npm** (required for interop tests)

## Building

Build the entire workspace using cargo:

```bash
cargo build --workspace
```

## Testing

We maintain strict interoperability with Node.js. Tests include unit tests, golden fixtures, and live interop tests.
Two suites must pass before merging:

Before running interop tests, install the Node.js dependencies:
```bash
cd peeroxide/tests/node && npm install && cd -
# Unit tests, integration tests, Node.js local interop
cargo test --workspace

# Live public HyperDHT network tests (requires internet)
cargo test -p peeroxide-cli --test live_commands -- --ignored
```

Run the test suite:
Before running tests, install the Node.js dependencies once:

```bash
# Run all workspace tests
cargo test --workspace
npm ci --prefix tests/node
```

# Run unit tests only
cargo test --workspace --lib
## Code Style

# Run interop tests (requires Node.js)
cargo test --workspace --test '*interop*'
```bash
# Must pass with zero warnings
cargo clippy --workspace --all-targets -- -D warnings

# Docs must build clean
cargo doc --workspace --no-deps
```

For more detailed testing information and specialized test suites, see [TESTING.md](./TESTING.md).
## API Stability

These three library crates are published at `>=1.0` and have external users.

**Any change to an existing public API signature is a breaking change and requires explicit maintainer approval before implementation.**

When in doubt, add a new function rather than changing an existing one.

## PR Checklist

### Before opening a PR

## Code Style and Quality
- [ ] Both test suites pass locally (see Testing above)
- [ ] Clippy clean
- [ ] No public API breaking changes without maintainer approval
- [ ] CHANGELOG updated for each affected crate
- [ ] Version bumps are correct per semver (patch / minor / major)
- [ ] New public API items have `///` doc comments
- [ ] No task-artifact files committed (planning docs, prompt files, checklists — see AGENTS.md)

We enforce high standards for code quality and documentation:
### Before merging

- **Clippy**: Must pass without warnings.
```bash
cargo clippy --workspace --all-targets -- -D warnings
```
- **Documentation**: Documentation builds must have zero warnings.
```bash
cargo doc --workspace --no-deps --document-private-items
```
- **Formatting**: Follow standard Rust formatting (rustfmt).
- [ ] GitHub Actions CI is green (all checks pass)
- [ ] PR has been reviewed and approved

## Pull Request Process
## Release Process

1. Ensure all tests pass, including interop tests if you modified protocol-sensitive code.
2. Run clippy and check that documentation builds without warnings.
3. Keep PRs focused on a single change or feature.
4. Update or add tests for any new functionality or bug fixes.
5. All commits must be clear and descriptive.
6. For API changes, run `cargo-semver-checks` to verify SemVer compliance:
```bash
cargo install cargo-semver-checks
cargo semver-checks check-release -p <crate>
```
Releases are managed by [release-plz](https://release-plz.eplr.dev/). On merge to `main`, release-plz opens a release PR with version bumps and changelog entries. Merging that PR publishes to crates.io automatically. Do not run `cargo publish` manually.

## Licensing

Peeroxide is dual-licensed under the MIT license and the Apache License (Version 2.0). By contributing, you agree that your contributions will be licensed under these terms.
Peeroxide is dual-licensed under MIT and Apache 2.0. By contributing, you agree your contributions will be licensed under the same terms.
Loading
Loading