pub mod artifact;
pub mod capability;
pub mod dynamic;
pub mod grants;
pub mod host;
pub mod manifest;
pub mod plugin;
pub mod slots;
pub mod wire;
#[cfg(any(test, feature = "test-support"))]
#[doc(hidden)]
pub mod test_guests;
pub use artifact::{
ArtifactError, MAX_ARTIFACT_BYTES, MAX_MANIFEST_BYTES, MAX_MODULE_BYTES, SandboxArtifact,
read_bounded,
};
pub use capability::{
ActivitySummary, CacheKvStore, CallResult, CallValue, CapabilityCall, CapabilityEvent,
CapabilityOutcome, CapabilityRateLimiter, CapabilityRuntime, CapabilityServices, DenialReason,
DroppedCalls, FragmentNode, JobSink, KvStore, MAX_DETAIL_CHARS, MAX_EVENTS, MAX_KV_KEY_BYTES,
MAX_LOG_EVENTS, MAX_OUTBOUND_HEADERS, MAX_RESPONSE_HEADER_BYTES, MAX_RESULT_BYTES,
MAX_ROW_BYTES, MAX_ROW_COLUMNS, MAX_ROW_ID_BYTES, MAX_TARGET_CHARS, MAX_VALUE_TEXT_BYTES,
MemoryJobSink, MemoryKvStore, MemoryPluginStore, NO_TENANT, OutboundHttp, OutboundRequest,
OutboundResponse, PluginActivityLog, PluginJob, PluginRow, PluginStore, PluginValue, QueryPage,
RecordingHttp, RenderError, Scope, StoreError, bounded_rows, row_weight, tenant_segment,
};
pub use dynamic::{
MountError, MountedPluginInfo, PluginMounts, framework_prefixes, mounts_fallback,
};
pub use grants::{
CapabilityGrants, CapabilityQuotas, ConsentDelta, MAX_GRANT_ENTRIES, MAX_GRANT_IDENT_LEN,
MAX_HOST_LEN, MAX_QUOTA, is_grantable_host, is_grantable_ident, is_grantable_name,
};
pub use host::{
CapabilityDenial, DeniedCapability, MAX_INIT_SECTION_BYTES, MAX_INIT_SEGMENTS,
MAX_QUEUED_REPLY_BYTES, MAX_RENDER_CONTEXT_BYTES, MAX_RENDER_CONTEXT_ENTRIES,
MAX_TABLE_ELEMENTS, RENDER_CONTEXT_ENTRY_OVERHEAD, SandboxFailure, SandboxHost,
SandboxLoadError, SandboxOutcome, SandboxRenderOutcome, bounded_context,
};
pub use manifest::{
DeclaredRoute, MAX_CONCURRENCY, MAX_FOOTPRINT_BYTES, MAX_FUEL, MAX_MEMORY_BYTES,
MAX_REQUEST_BODY_BYTES, MAX_REQUEST_BODY_TIMEOUT_MS, MAX_RESPONSE_BYTES, ManifestError,
ResourceLimits, SandboxCapability, SandboxManifest, WIRE_VERSION,
};
pub use plugin::{
DEFAULT_GUEST_SLOTS, SANDBOX_ATTRIBUTION_HEADER, SandboxPluginError, SandboxedPlugin,
set_guest_slots,
};
pub use slots::{RenderSlots, SlotError};
pub use wire::{
ALLOWED_REQUEST_HEADERS, ALLOWED_RESPONSE_CONTENT_TYPES, ALLOWED_RESPONSE_HEADERS, OwnedRoutes,
SandboxRequest, SandboxResponse, WireError, request_header_allowed, response_header_allowed,
};
#[doc(hidden)]
#[must_use]
pub fn __fuzz_read_artifact(bytes: &[u8]) -> bool {
SandboxArtifact::read(bytes).is_ok()
}
#[doc(hidden)]
#[must_use]
pub fn __fuzz_parse_guest_frame(line: &str) -> bool {
wire::from_guest_line(line).is_ok()
}
#[doc(hidden)]
#[must_use]
pub fn __fuzz_parse_manifest(src: &str) -> bool {
SandboxManifest::parse(src).is_ok()
}
#[doc(hidden)]
#[must_use]
pub fn __fuzz_render_fragment(line: &str) -> bool {
let _budget = capability::FragmentNodeBudget::reserve(capability::render::MAX_NODES);
let Ok(nodes) = serde_json::from_str::<Vec<capability::FragmentNode>>(line) else {
return false;
};
capability::render::render(&nodes, 64 * 1024).is_ok()
}
#[cfg(test)]
mod manifest_guard {
const MANIFEST: &str = include_str!("../../Cargo.toml");
fn feature_line() -> &'static str {
MANIFEST
.lines()
.map(str::trim)
.find(|line| line.starts_with("plugin-sandbox ="))
.expect("the plugin-sandbox feature is declared")
}
#[test]
fn the_feature_adds_exactly_one_dependency() {
assert_eq!(
feature_line(),
r#"plugin-sandbox = ["dep:wasmi"]"#,
"enabling the sandbox must pull in the interpreter and nothing else"
);
}
#[test]
fn the_interpreter_is_optional_so_a_default_build_never_links_it() {
let wasmi = MANIFEST
.lines()
.map(str::trim)
.find(|line| line.starts_with("wasmi ="))
.expect("wasmi is a dependency");
assert!(wasmi.contains("optional = true"), "{wasmi}");
let default = MANIFEST
.lines()
.map(str::trim)
.find(|line| line.starts_with("default = ["))
.expect("a default feature set");
assert!(
!default.contains("plugin-sandbox"),
"the sandbox must stay opt-in: {default}"
);
}
}