- Create quicproquo-ffi crate with 7 extern "C" functions: connect, login, send, receive, disconnect, last_error, free_string (produces libquicproquo_ffi.so and .a) - Feature-gate quicproquo-core for WASM: identity, hybrid_kem, safety_numbers, sealed_sender, app_message, padding, transcript all compile to wasm32-unknown-unknown - Add Python ctypes example (examples/python/qpq_client.py) with QpqClient wrapper class and CLI - Add SDK documentation: FFI reference, WASM guide, qpq-gen generators - Update Dockerfile for quicproquo-ffi workspace member
172 lines
5.3 KiB
Markdown
172 lines
5.3 KiB
Markdown
# Code Generators (qpq-gen)
|
|
|
|
The `qpq-gen` CLI tool scaffolds new plugins, bots, RPC methods, and hook
|
|
events for the quicproquo ecosystem.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
cargo install --path crates/quicproquo-gen
|
|
```
|
|
|
|
Or run directly from the workspace:
|
|
|
|
```bash
|
|
cargo run -p quicproquo-gen -- <subcommand>
|
|
```
|
|
|
|
## Subcommands
|
|
|
|
### `qpq-gen plugin <name>` -- Server Plugin
|
|
|
|
Scaffolds a standalone Cargo project for a server plugin compiled as a shared
|
|
library (`cdylib`). The generated plugin implements the `HookVTable` C ABI
|
|
and is loaded by the server at startup via `--plugin-dir`.
|
|
|
|
```bash
|
|
qpq-gen plugin rate-limiter
|
|
qpq-gen plugin audit-log --output /tmp/plugins
|
|
```
|
|
|
|
**Generated files:**
|
|
|
|
```
|
|
rate_limiter/
|
|
Cargo.toml # cdylib crate depending on quicproquo-plugin-api
|
|
README.md # Build and install instructions
|
|
src/lib.rs # Plugin skeleton with qpq_plugin_init entry point
|
|
```
|
|
|
|
The template includes:
|
|
- `qpq_plugin_init` -- called by the server on load; populates the `HookVTable`
|
|
- `on_message_enqueue` -- sample hook that rejects payloads larger than 1 MB
|
|
- `error_message` -- returns the rejection reason as a C string
|
|
- `destroy` -- frees the plugin state
|
|
|
|
**What to customize:** Replace the `on_message_enqueue` logic with your own
|
|
policy. Add more hooks by setting additional fields on the `HookVTable`
|
|
(`on_auth`, `on_channel_created`, `on_fetch`, `on_user_registered`,
|
|
`on_batch_enqueue`).
|
|
|
|
**Build and install:**
|
|
|
|
```bash
|
|
cd rate_limiter
|
|
cargo build --release
|
|
cp target/release/librate_limiter.so /path/to/plugins/
|
|
qpq-server --plugin-dir /path/to/plugins/
|
|
```
|
|
|
|
### `qpq-gen bot <name>` -- Bot Project
|
|
|
|
Scaffolds a standalone bot project using the Bot SDK. The generated binary
|
|
connects to a quicproquo server, authenticates via OPAQUE, and runs a
|
|
message-handling loop.
|
|
|
|
```bash
|
|
qpq-gen bot echo-bot
|
|
qpq-gen bot moderation-bot --output /tmp/bots
|
|
```
|
|
|
|
**Generated files:**
|
|
|
|
```
|
|
moderation_bot/
|
|
Cargo.toml # Binary crate depending on quicproquo-bot + tokio
|
|
README.md # Quick-start and command reference
|
|
src/main.rs # Bot skeleton with handle_message dispatcher
|
|
```
|
|
|
|
The template ships with four built-in commands as examples:
|
|
|
|
| Command | Description |
|
|
|-----------------|---------------------------|
|
|
| `!help` | List available commands |
|
|
| `!echo <text>` | Echo back the text |
|
|
| `!whoami` | Show the sender's username|
|
|
| `!ping` | Respond with "pong!" |
|
|
|
|
**Configuration** is read from environment variables:
|
|
|
|
| Variable | Default |
|
|
|-------------------|----------------------|
|
|
| `QPQ_SERVER` | `127.0.0.1:7000` |
|
|
| `QPQ_USERNAME` | `<bot-name>` |
|
|
| `QPQ_PASSWORD` | `changeme` |
|
|
| `QPQ_CA_CERT` | `server-cert.der` |
|
|
| `QPQ_STATE_PATH` | `<bot-name>-state.bin` |
|
|
|
|
**What to customize:** Edit the `handle_message` function in `src/main.rs`
|
|
to add your own command handlers. Return `Some(response)` to reply, or
|
|
`None` to stay silent.
|
|
|
|
**Run:**
|
|
|
|
```bash
|
|
cd moderation_bot
|
|
QPQ_SERVER=127.0.0.1:7000 \
|
|
QPQ_USERNAME=moderation_bot \
|
|
QPQ_PASSWORD=changeme \
|
|
QPQ_CA_CERT=path/to/server-cert.der \
|
|
cargo run
|
|
```
|
|
|
|
### `qpq-gen rpc <Name>` -- RPC Method Guide
|
|
|
|
Prints a step-by-step guide for adding a new Cap'n Proto RPC method to the
|
|
server. This generator does not create files; it outputs instructions and
|
|
code snippets to copy into the appropriate locations.
|
|
|
|
```bash
|
|
qpq-gen rpc listChannels
|
|
```
|
|
|
|
The `Name` argument should be in camelCase (e.g., `listChannels`). The
|
|
generator derives the `snake_case` form automatically for file and function
|
|
names.
|
|
|
|
**Steps covered:**
|
|
|
|
1. **Schema** -- Add the method to the `interface NodeService` block in
|
|
`schemas/node.capnp`, then rebuild with `cargo build -p quicproquo-proto`
|
|
2. **Handler module** -- Create
|
|
`crates/quicproquo-server/src/node_service/<name>.rs` with the handler
|
|
implementation (template code is printed)
|
|
3. **Registration** -- Wire the handler into `node_service/mod.rs`
|
|
4. **Storage** (if needed) -- Add a method to the `Store` trait and implement
|
|
it in `sql_store.rs` and `storage.rs`
|
|
5. **Hook** (optional) -- Run `qpq-gen hook <name>` to let plugins observe
|
|
the new RPC
|
|
6. **Verify** -- `cargo build -p quicproquo-server && cargo test -p quicproquo-server`
|
|
|
|
### `qpq-gen hook <name>` -- Hook Event Guide
|
|
|
|
Prints a step-by-step guide for adding a new server hook event that plugins
|
|
can observe. Like `rpc`, this generator outputs instructions rather than
|
|
creating files.
|
|
|
|
```bash
|
|
qpq-gen hook message_deleted
|
|
```
|
|
|
|
The `name` argument should be in `snake_case` (e.g., `message_deleted`). The
|
|
generator derives the `PascalCase` form for struct names.
|
|
|
|
**Steps covered:**
|
|
|
|
1. **Event struct** -- Define `MessageDeletedEvent` in
|
|
`crates/quicproquo-server/src/hooks.rs`
|
|
2. **Trait method** -- Add `on_message_deleted` to the `ServerHooks` trait
|
|
with a default no-op implementation
|
|
3. **Tracing** -- Implement the hook in `TracingHooks` with a `tracing::info!`
|
|
call
|
|
4. **Plugin API** -- Add a C-compatible `CMessageDeletedEvent` struct and an
|
|
`on_message_deleted` field to `HookVTable` in
|
|
`crates/quicproquo-plugin-api/src/lib.rs`
|
|
5. **Plugin dispatch** -- Wire the conversion and dispatch in
|
|
`plugin_loader.rs`
|
|
6. **Call site** -- Fire the hook from the relevant RPC handler in
|
|
`node_service/`
|
|
7. **Verify** -- Build and test `quicproquo-plugin-api` and
|
|
`quicproquo-server`
|