feat: Sprint 3 — C FFI bindings, WASM compilation, Python example, SDK docs
- 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
This commit is contained in:
171
docs/src/getting-started/generators.md
Normal file
171
docs/src/getting-started/generators.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user