add docs, protocol, plugins, README, CHANGELOG
This commit is contained in:
parent
1d2209bfac
commit
f262da222b
44 changed files with 9269 additions and 0 deletions
176
docs/community/contributing.md
Normal file
176
docs/community/contributing.md
Normal 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
188
docs/community/plugins.md
Normal 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue