add docs, protocol, plugins, README, CHANGELOG

This commit is contained in:
loki5512344 2026-07-09 12:30:55 +02:00
parent 1d2209bfac
commit f262da222b
Signed by: boba
GPG key ID: 253067914055423B
44 changed files with 9269 additions and 0 deletions

View file

@ -0,0 +1,176 @@
# Contributing
---
## License
VNOX is licensed under **GPL-3.0**. See `../LICENSE.md` for the full text and
what this means for plugins and protocol implementations.
The LNEx protocol specification is additionally licensed under **CC0** (public domain) —
anyone can implement it under any license.
---
## Before you start
1. Check existing issues — your idea or bug may already be tracked.
2. For significant changes, open an issue first to discuss approach.
3. For small fixes (typos, docs, obvious bugs), PRs are welcome directly.
---
## Setting up the dev environment
### Prerequisites
- Rust stable (latest) — `rustup update stable`
- System audio libraries:
- Linux: `apt install libasound2-dev libopus-dev pkg-config`
- macOS: `brew install opus`
- Windows: opus ships with the crate, no extra step
- Docker (optional, for running a local node)
### Build
```bash
git clone https://github.com/vnox/vnox
cd vnox
# Build everything
cargo build
# Build release
cargo build --release
# Run gateway (dev mode)
cargo run -p vnox-gateway -- --config dev/config.toml
# Run voice node
cargo run -p vnox-voice-node -- --config dev/config.toml
# Run client
cargo run -p vnox-client
```
### Running tests
```bash
# All tests
cargo test
# Specific crate
cargo test -p vnox-gateway
# With logs
RUST_LOG=debug cargo test -p vnox-gateway -- --nocapture
```
---
## Repository structure
```
vnox/
├── client/ # Desktop client (egui + wgpu)
│ └── src/
│ ├── ui/ # egui panels and widgets
│ ├── audio/ # cpal capture/playback, Opus encode/decode
│ ├── net/ # LNEx client, quinn UDP
│ └── identity/ # keypair, auth
│
├── gateway/ # TCP gateway
│ └── src/
│ ├── auth/ # identity verification, sessions
│ ├── channels/ # channel management
│ ├── proto/ # LNEx packet handling
│ └── storage/ # SQLite / Postgres
│
├── voice-node/ # UDP voice relay
│ └── src/
│ ├── relay/ # packet routing per channel
│ └── jitter/ # jitter buffer
│
├── protocol/ # LNEx .proto schemas
│ └── *.proto
│
├── plugins/ # Plugin runtime + example plugins
│ └── examples/
│
├── sdk/ # Client SDK (future)
├── docs/ # This documentation
└── dev/ # Dev config, test fixtures
└── config.toml
```
---
## Code style
- `cargo fmt` before committing — enforced in CI
- `cargo clippy -- -D warnings` must pass — enforced in CI
- No `unwrap()` in library code — use proper error propagation
- No `unsafe` without a comment explaining why it's safe
- Public API items must have doc comments
---
## Commit messages
Follow conventional commits:
```
feat(gateway): add rate limiting per IP
fix(client): handle reconnect on TCP drop
docs(protocol): clarify voice packet sequence field
chore(deps): update tokio to 1.37
```
Types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `perf`
Scope is the crate or subsystem: `gateway`, `client`, `voice-node`, `protocol`, `docs`.
---
## Pull requests
- Keep PRs focused — one concern per PR
- Include tests for non-trivial changes
- Update docs if the change affects user-facing behavior
- CI must pass before merge
PR title follows the same format as commit messages.
---
## Governance
VNOX uses the **BDFL model** — the maintainer makes final decisions on all matters.
For large or breaking changes (especially LNEx protocol changes), open an issue
and discuss before implementing. Protocol PRs without prior discussion will not be merged.
---
## Protocol changes
Changes to the LNEx protocol are treated differently from implementation changes.
- Any change to packet format, auth flow, or behavior must be documented
in `docs/02-protocol/` before implementation
- Breaking changes require a LNEx version bump
- Non-breaking additions are allowed within the same version with a changelog entry
- Protocol PRs require more review time than implementation PRs
---
## Where to start
Good first issues are tagged `good first issue` on GitHub.
If you want to contribute but don't know where:
1. Run a node locally and report anything confusing about the setup process
2. Improve documentation — anything unclear in `docs/` is a valid fix
3. Write tests for existing gateway or voice-node code
4. Implement a feature from the Phase 1 checklist in `../06-roadmap.md`

188
docs/community/plugins.md Normal file
View file

@ -0,0 +1,188 @@
# Plugins
VNOX has a plugin system for extending server-side behavior.
Plugins run on the node, not on the client.
---
## Supported languages
- TypeScript
- JavaScript
---
## Runtime
**Deno** — chosen as the plugin runtime.
Reasons:
- TypeScript native, no transpile step for plugin authors
- built-in permissions model — plugins explicitly declare what they need
- active ecosystem, good Rust embedding via `deno_core`
---
## API
Plugins communicate with the gateway via **WebSocket RPC**.
The gateway exposes a local WebSocket endpoint that plugins connect to.
```
Plugin process
│ WebSocket (localhost)
▼
Gateway plugin API (localhost:7800)
```
### RPC format
```json
{
"id": "req-1",
"method": "channel.send_message",
"params": {
"channel_id": "general",
"content": "Hello from plugin"
}
}
```
Response:
```json
{
"id": "req-1",
"result": { "message_id": "abc123" }
}
```
Errors:
```json
{
"id": "req-1",
"error": { "code": 403, "message": "permission denied" }
}
```
---
## Available methods
### Events (subscribe)
```typescript
// Subscribe to all events
ws.on('message', (event) => {
const e = JSON.parse(event);
// e.event, e.data
});
```
| Event | Payload |
|-------|---------|
| `user.join` | `{ user_id, channel_id }` |
| `user.leave` | `{ user_id, channel_id }` |
| `message.created` | `{ message_id, channel_id, sender_id, content }` |
| `voice.speaking` | `{ user_id, channel_id, state }` |
| `user.muted` | `{ user_id }` |
### Commands
| Method | Description |
|--------|-------------|
| `channel.send_message` | Send a message to a channel |
| `channel.list` | List all channels |
| `user.kick` | Kick a user from a channel |
| `user.mute` | Mute a user (server-side) |
| `user.ban` | Ban a user by pubkey |
| `user.get` | Get user info by pubkey |
| `node.get_stats` | Get node statistics |
---
## Plugin manifest
Each plugin is a directory with a `plugin.json`:
```json
{
"name": "relay-switcher",
"version": "0.1.2",
"author": "raven",
"description": "Auto-selects the nearest relay node",
"main": "index.ts",
"permissions": [
"node.stats",
"channel.read"
]
}
```
Permissions are declared in the manifest and granted by the node admin.
A plugin that requests permissions not granted to it will receive `403` on those methods.
---
## Example plugin
A simple moderation bot that deletes messages containing a banned word:
```typescript
// index.ts
const ws = new WebSocket("ws://localhost:7800/plugins");
const BANNED = ["badword"];
ws.addEventListener("message", async (event) => {
const e = JSON.parse(event.data);
if (e.event === "message.created") {
const { message_id, channel_id, content } = e.data;
const lower = content.toLowerCase();
if (BANNED.some(word => lower.includes(word))) {
await rpc("message.delete", { message_id, channel_id });
console.log(`Deleted message ${message_id}`);
}
}
});
function rpc(method: string, params: object): Promise<any> {
return new Promise((resolve) => {
const id = crypto.randomUUID();
ws.send(JSON.stringify({ id, method, params }));
ws.addEventListener("message", function handler(e) {
const res = JSON.parse(e.data);
if (res.id === id) {
ws.removeEventListener("message", handler);
resolve(res.result);
}
});
});
}
```
---
## Installing a plugin
```bash
# Copy plugin directory to node's plugin folder
cp -r my-plugin/ /var/lib/vnox/plugins/
# Restart gateway (or use hot-reload if supported)
systemctl restart vnox-gateway
```
Or via the client: Settings → Plugins → Install → select directory.
---
## Plugin marketplace
A community plugin registry is planned for Phase 3.
Plugins will be installable directly from the client.
Until then, plugins are distributed as source code repositories.