vgi-rpc
Rust library for the
vgi-rpc transport-agnostic
RPC framework built on Apache Arrow IPC. Byte-for-byte wire-compatible
with the Python canonical implementation and the Go port — this crate
passes the complete 868-test Python conformance suite across
pipe, subprocess, HTTP, Unix-socket, externalised-upload, and
shared-memory pipe transports.
Stock arrow-rs 58.x dependency tree, MSRV 1.86, no
[patch.crates-io] required.
Highlights
- Server-side dispatch for unary, producer, and exchange stream methods over stdio / Unix socket / HTTP / shared memory.
- Introspection via the built-in
__describe__method (DESCRIBE_VERSION = "4", slim wire format plusprotocol_hash). - HTTP surface — axum-backed server with HMAC-signed stateless stream-state tokens, CORS + preflight, zstd request/response compression, configurable URL prefix, landing / describe / health pages, RFC 9728 Protected Resource Metadata, configurable response / externalised-response caps.
- Auth — bearer (constant-time compare), mTLS via RFC 8705
x-forwarded-client-cert, OAuth 2 Protected Resource Metadata; JWKS-backed JWT (single-flight refresh) and OAuth 2 PKCE primitives behind Cargo features. - Observability —
DispatchHook+CallStatistics, schema-validated structured access logs, realtracing::Spanemission fortracing-opentelemetry, two-tier Sentry integration (tracing-only or full SDK). - Lifecycle —
TransportKind+on_serve_starthook so workers can tailor startup work to the bound transport (pipe / HTTP / unix / shared-memory). - External locations — transparent upload of oversized batches to
pluggable
ExternalStoragebackends (vgi-rpc-s3/vgi-rpc-gcs), SHA-256 integrity, optional zstd, post-decompression size cap. - DoS-resilience by construction — wire reader rejects
oversized IPC schema length prefixes (
MAX_IPC_SCHEMA_BYTES = 16 MiB) and per-message flatbufferbodyLength(MAX_IPC_MESSAGE_BYTES = 256 MiB) before allocating, blocking the trivial 4-byte and 50-byte OOM payloadsfuzz/wire_stream_readerdiscovered. - Graceful shutdown on SIGTERM / SIGINT for both HTTP and Unix listeners.
Cargo features
| feature | default | enables |
|---|---|---|
http |
✅ | Axum HTTP server + external-location helpers + stream-state tokens. |
macros |
✅ | #[service], #[unary], #[producer], #[exchange], #[derive(VgiArrow)], #[derive(StreamState)]. |
jwt |
JwtConfig / Jwks types only — bring your own verifier. |
|
jwt-jsonwebtoken |
Bundled JWT verifier (jsonwebtoken + reqwest JWKS fetcher). |
|
oauth-pkce |
auth::pkce cookie + verifier crypto primitives. |
|
oauth-pkce-server |
OAuth 2 PKCE server-side redirect / token-exchange (reqwest). |
|
mtls-pem |
PEM-cert parsing helpers (x509-parser). XFCC parsing is always on. |
|
otel |
OtelHook — real tracing::Span per RPC for tracing-opentelemetry. |
|
sentry-tracing |
TracingSentryHook — lightweight, no extra deps. |
|
sentry-sdk |
SentrySdkHook — full Sentry SDK integration (sentry 0.46). |
|
shm |
POSIX shared-memory transport (zero-copy producer / exchange). | |
test-utils |
external::InMemoryStorage fixture for downstream tests. |
Minimal example
use Arc;
use ;
use ;
use ;
use HttpState;
async
Public surface cheat sheet
use ;
// Feature-gated:
use bearer_authenticate_static; // always on
use mtls_authenticate_fingerprint; // always on
use ; // "http"
use ; // "http"
// use vgi_rpc::auth::jwt::jwt_authenticate; // "jwt"
// use vgi_rpc::auth::pkce::generate_pkce_pair; // "oauth-pkce"
// use vgi_rpc::{OtelConfig, OtelHook, OtelMetrics}; // "otel"
// use vgi_rpc::{TracingSentryConfig, TracingSentryHook}; // "sentry-tracing"
// use vgi_rpc::{SentrySdkConfig, SentrySdkHook}; // "sentry-sdk"
Macros (default-on macros feature)
use Arc;
use ;
;
let mut srv = builder.protocol_name.build;
register_with;
#[derive(VgiArrow)] derives a struct's Arrow Struct<fields> data
type for any field that itself implements VgiArrow (mirroring
Python's ArrowSerializableDataclass). #[derive(StreamState)]
auto-impls StreamStateCodec (bincode) on stream-state types.
Interoperability notes
The wire protocol matches Python's vgi_rpc canonical:
- Pointer-batch schema is empty; location metadata is the payload.
__describe__version is"4";method_typecollapses Producer / Exchange / Dynamic into"stream". The describe response carries aprotocol_hashSHA-256 digest computed identically to Python's algorithm.- Access log records carry
logger: "vgi_rpc.access"and validate cleanly against Python'svgi_rpc.access_log_conformanceJSON Schema.request_datais truncated at INFO level (replaced withoriginal_request_bytes+truncated: true) — opt in viaAccessLogHook::with_verbose(true)to get full payloads. - HTTP stream-state tokens are HMAC-SHA256-signed (token format v3,
identical byte layout to Python's
_state_token.py); set an explicit signing key withHttpStateBuilder::signing_key_*so tokens survive across worker restarts and load balancing. - Pyarrow's default nullability (
listinner /mapvalues / dynamic schema fields =nullable=true) is honored.
License
Apache-2.0.