Expand description
Capability-gated outbound TCP for sandboxed WASM connectors (FIDIUS-I-0033).
Portable (backed by std::net → wasi:sockets), so present in host builds too.
Capability-gated outbound TCP for sandboxed WASM connectors (FIDIUS-I-0033) —
the raw-wire counterpart of [http], for DB/warehouse drivers. Backed by
std::net::TcpStream (which is wasi:sockets on wasm32-wasip2), so it is
portable: present on the host too (a normal socket), no cfg(wasm) gate.
fidius::sockets — capability-gated outbound TCP for sandboxed WASM
connectors (FIDIUS-I-0033).
This is the missing seam for connectors that speak a raw binary wire protocol
over TCP rather than HTTP — most importantly database/warehouse drivers (e.g.
Postgres on :5432), which a host can’t broker as HTTP. A pure-Rust sync
driver built on [tcp::TcpStream] (with rustls layered on top for TLS) runs
fully sandboxed, closing the last gap that kept DB connectors on the retired
native path.
§Backed by std::net → wasi:sockets
Unlike [crate::http] (which wraps wasi:http because std has no HTTP), TCP
needs no hand-written WIT: on wasm32-wasip2 Rust’s std::net::TcpStream
is wasi:sockets (since Rust 1.83, std’s net layer calls wasi-libc’s
socket functions). So [tcp::TcpStream] is a thin, blocking wrapper over
std::net::TcpStream and is portable: identical source compiles for the
host (a normal socket) and for wasm32-wasip2 (a sandboxed one). Sync/blocking
semantics suit the off-tokio block_on execution model.
§Two-key, fail-closed — the same gate as http
A connect only succeeds when both keys are turned:
- the package declares the
tcpcapability in[wasm].capabilities, and - the host supplied an
EgressPolicywhoseauthorize_tcp(host:port)allows the (resolved) peer.
Miss either and the connect is refused (the deny-all WasiCtx default) — there
is no ambient network. The guest sees a normal std::io::Error; it never
learns the policy’s reasoning, by design.
use std::io::{Read, Write};
use fidius_guest::sockets::tcp;
// Allowed only if the host's EgressPolicy::authorize_tcp permits db:5432.
let mut conn = tcp::connect("db.internal", 5432)?;
conn.write_all(startup_packet)?;
let mut buf = [0u8; 1024];
let n = conn.read(&mut buf)?;TcpStream implements [Read] + [Write], so a TLS layer composes directly:
let mut tls = rustls::Stream::new(&mut client_conn, &mut conn);
tls.write_all(startup_packet)?; // TLS over the sandboxed TCP streamModules§
- tcp
- Blocking outbound TCP, the policy-gated counterpart of [
crate::http].