Skip to main content

bext_plugin_api/
types.rs

1//! Shared types for the plugin API: [`PluginManifest`], [`PluginCapability`],
2//! priority constants, and fuel budget defaults for WASM execution.
3
4/// Manifest returned by a plugin during initialization.
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
6pub struct PluginManifest {
7    pub name: String,
8    pub version: String,
9    #[serde(default)]
10    pub description: String,
11    #[serde(default)]
12    pub capabilities: Vec<PluginCapability>,
13    // TODO: coordinate with bext-registry R3 schema bump
14    #[serde(default)]
15    pub requires_capabilities: Vec<PluginCapability>,
16    #[serde(default)]
17    pub provides_capabilities: Vec<PluginCapability>,
18}
19
20/// What a plugin can do.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
22#[serde(rename_all = "snake_case")]
23pub enum PluginCapability {
24    Transform,
25    Middleware,
26    CacheBackend,
27    Lifecycle,
28    Auth,
29    Session,
30    Mailer,
31    Tracer,
32    Scheduled,
33    Webhook,
34    FeatureFlag,
35    Locking,
36    I18n,
37    StorageClient,
38    SearchClient,
39    AuthzPolicy,
40}
41
42/// Permissions for WASM plugins (sandbox limits).
43#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
44pub struct WasmPluginPermissions {
45    /// Allowed URL patterns for http_fetch (glob matching).
46    #[serde(default)]
47    pub allowed_urls: Vec<String>,
48    /// Storage quota in KB. Default: 1024 (1 MB).
49    #[serde(default = "default_storage_quota")]
50    pub storage_quota_kb: u64,
51    /// Max HTTP fetches per minute. Default: 30.
52    #[serde(default = "default_max_fetch")]
53    pub max_fetch_per_minute: u32,
54    /// Allowed KV namespaces. Empty = no KV access.
55    #[serde(default)]
56    pub kv_namespaces: Vec<String>,
57    /// Allowed queue names. Empty = no queue access.
58    #[serde(default)]
59    pub queue_names: Vec<String>,
60}
61
62fn default_storage_quota() -> u64 {
63    1024
64}
65
66fn default_max_fetch() -> u32 {
67    30
68}
69
70impl Default for WasmPluginPermissions {
71    fn default() -> Self {
72        Self {
73            allowed_urls: Vec::new(),
74            storage_quota_kb: default_storage_quota(),
75            max_fetch_per_minute: default_max_fetch(),
76            kv_namespaces: Vec::new(),
77            queue_names: Vec::new(),
78        }
79    }
80}
81
82// ---------------------------------------------------------------------------
83// Priority constants — document the default ordering for built-in components
84// so plugin authors know where to insert.
85// ---------------------------------------------------------------------------
86
87/// Built-in middleware priorities.
88pub mod priority {
89    /// CORS middleware (outermost).
90    pub const CORS: u32 = 100;
91    /// Rate limiter.
92    pub const RATE_LIMIT: u32 = 200;
93    /// JWT / session auth.
94    pub const AUTH: u32 = 300;
95    /// Tenant resolver.
96    pub const TENANT: u32 = 400;
97    /// Request tracing (innermost built-in).
98    pub const TRACING: u32 = 500;
99    /// Default priority for plugin middleware.
100    pub const PLUGIN_DEFAULT: u32 = 600;
101}
102
103/// Built-in transform priorities.
104pub mod transform_priority {
105    pub const FLOW_EXTRACT: u32 = 100;
106    pub const BARREL_OPTIMIZE: u32 = 200;
107    pub const FONT_OPTIMIZE: u32 = 250;
108    pub const IMPORT_STRIP: u32 = 300;
109    pub const SHIM_INJECT: u32 = 350;
110    pub const CSS_MODULE: u32 = 400;
111    pub const ENV_INLINE: u32 = 500;
112    pub const SERVER_BOUNDARY: u32 = 600;
113    pub const CACHE_DIRECTIVE: u32 = 700;
114    /// Default priority for plugin transforms (after all built-ins).
115    pub const PLUGIN_DEFAULT: u32 = 1000;
116}
117
118/// Sandbox runtime type for user-supplied plugins.
119#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
120#[serde(rename_all = "snake_case")]
121pub enum SandboxType {
122    /// Compiled WASM module executed via wasmtime. Best for Rust/Go/C plugins.
123    /// Sub-millisecond startup, 1-5MB per instance, fuel-budgeted execution.
124    Wasm,
125    /// JavaScript executed via QuickJS (embedded interpreter). Best for tenant
126    /// scripting — pricing rules, transforms, webhook handlers.
127    /// Sub-millisecond startup, <1MB per instance, no filesystem/network by default.
128    QuickJs,
129    /// Arbitrary executable run inside an nsjail process sandbox. Best when
130    /// WASM/QuickJS are too restrictive — full Linux userspace with namespace,
131    /// cgroup, and seccomp isolation.
132    /// ~10ms startup, near-zero memory overhead, requires nsjail binary.
133    Nsjail,
134}
135
136/// Permissions shared across all sandbox types.
137#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
138pub struct SandboxPermissions {
139    /// Allowed URL patterns for outbound HTTP (glob matching).
140    #[serde(default)]
141    pub allowed_urls: Vec<String>,
142    /// Storage quota in KB. Default: 1024 (1 MB).
143    #[serde(default = "default_storage_quota")]
144    pub storage_quota_kb: u64,
145    /// Max HTTP fetches per minute. Default: 30.
146    #[serde(default = "default_max_fetch")]
147    pub max_fetch_per_minute: u32,
148    /// Max memory in MB (QuickJS/nsjail). Default: 64.
149    #[serde(default = "default_max_memory_mb")]
150    pub max_memory_mb: u64,
151    /// Max wall-clock execution time in seconds per call. Default: 10.
152    #[serde(default = "default_max_time_secs")]
153    pub max_time_secs: u64,
154}
155
156fn default_max_memory_mb() -> u64 {
157    64
158}
159fn default_max_time_secs() -> u64 {
160    10
161}
162
163impl Default for SandboxPermissions {
164    fn default() -> Self {
165        Self {
166            allowed_urls: Vec::new(),
167            storage_quota_kb: default_storage_quota(),
168            max_fetch_per_minute: default_max_fetch(),
169            max_memory_mb: default_max_memory_mb(),
170            max_time_secs: default_max_time_secs(),
171        }
172    }
173}
174
175/// Fuel budgets for WASM plugin calls.
176pub mod fuel {
177    pub const ON_REQUEST_COMPLETE: u64 = 100_000_000;
178    pub const ON_CACHE_WRITE: u64 = 50_000_000;
179    pub const ON_CACHE_INVALIDATE: u64 = 50_000_000;
180    pub const ON_RELOAD: u64 = 200_000_000;
181    pub const ON_SERVER_START: u64 = 500_000_000;
182    pub const CLEANUP: u64 = 100_000_000;
183}