You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document defines the technical architecture for implementing a Dynamic Plugin System that allows users to extend the CreatorWeave with custom analysis capabilities. Users can upload external WASM plugin files to perform specific file analysis operations (MD5 calculation, code line counting, duplicate file detection, etc.) without modifying the core application.
Key Design Principles
Principle
Description
Sandbox Security
All plugins execute in an isolated WASM sandbox with no access to host system resources
Stable ABI
Well-defined plugin interface that remains compatible across versions
Hot Loading
Plugins can be loaded/unloaded at runtime without application restart
Progressive Enhancement
Core functionality works without plugins; plugins enhance capabilities
Developer Friendly
Plugin development follows standard Rust/WASM patterns with minimal boilerplate
Architecture Goals
Security First: Prevent malicious code execution through comprehensive sandboxing
Performance: Support analyzing 10,000+ files with plugin overhead <20%
Extensibility: Enable plugin authors to implement any file analysis operation
Usability: Non-technical users can install and use plugins easily
The plugin must export a bfosa_plugin_info function that returns plugin metadata:
// Rust side - plugin implementationuse serde::{Deserialize,Serialize};#[derive(Serialize,Deserialize)]pubstructPluginInfo{/// Plugin identifier (e.g., "md5-calculator")pubid:String,/// Human-readable namepubname:String,/// Plugin version (semver)pubversion:String,/// CreatorWeave core version required (semver range)pubapi_version:String,/// Plugin descriptionpubdescription:String,/// Plugin authorpubauthor:String,/// Plugin capabilitiespubcapabilities:PluginCapabilities,/// Resource limits requestedpubresource_limits:ResourceLimits,}#[derive(Serialize,Deserialize)]pubstructPluginCapabilities{/// Can process file metadata without contentpubmetadata_only:bool,/// Requires file content for processingpubrequires_content:bool,/// Supports streaming content (for large files)pubsupports_streaming:bool,/// Maximum file size to process (0 = unlimited)pubmax_file_size:u64,/// Supported file extensions (empty = all)pubfile_extensions:Vec<String>,}#[derive(Serialize,Deserialize)]pubstructResourceLimits{/// Maximum memory in bytespubmax_memory:u64,/// Maximum execution time per file (ms)pubmax_execution_time:u32,/// Requested Web Workers (0 = none)pubworker_count:u32,}
1.2.2 File Processing Interface
/// Input data for processing a single file#[derive(Serialize,Deserialize)]pubstructFileInput{/// File namepubname:String,/// File pathpubpath:String,/// File size in bytespubsize:u64,/// File MIME type (if available)pubmime_type:Option<String>,/// Last modified timestamppublast_modified:u64,/// File content (if plugin requires it)/// For large files, this is a chunk (see streaming below)pubcontent:Option<Vec<u8>>,}/// Output data for a processed file#[derive(Serialize,Deserialize)]pubstructFileOutput{/// File path (must match input)pubpath:String,/// Processing statuspubstatus:ProcessingStatus,/// Analysis results (plugin-specific JSON)pubdata: serde_json::Value,/// Error message (if status is Error)puberror:Option<String>,}#[derive(Serialize,Deserialize)]pubenumProcessingStatus{/// Successfully processedSuccess,/// Skipped (e.g., unsupported file type)Skipped,/// Error during processingError,}/// Final aggregated result after all files processed#[derive(Serialize,Deserialize)]pubstructPluginResult{/// Summary messagepubsummary:String,/// Total files processedpubfiles_processed:u64,/// Files skippedpubfiles_skipped:u64,/// Files with errorspubfiles_with_errors:u64,/// Aggregated metrics (plugin-specific)pubmetrics: serde_json::Value,/// Warnings collected during processingpubwarnings:Vec<String>,}
1.2.3 Required Plugin Exports
Export Name
Signature
Description
bfosa_plugin_info
() -> PluginInfo
Returns plugin metadata
bfosa_process_file
(input: FileInput) -> FileOutput
Process a single file
bfosa_finalize
(outputs: FileOutput[]) -> PluginResult
Aggregate results
bfosa_cleanup
() -> void
Clean up resources
1.2.4 Optional Streaming Interface
For plugins that need to process large files:
/// Initialize processing for a file (called once per file)pubfnbfosa_init_file(input:FileInput) -> FileContext;/// Process a chunk of file content (called multiple times)pubfnbfosa_process_chunk(context:FileContext,chunk:&[u8],offset:u64,) -> ChunkProgress;/// Finalize file processing after all chunks processedpubfnbfosa_finalize_file(context:FileContext) -> FileOutput;/// Clean up file contextpubfnbfosa_cleanup_file(context:FileContext);
1.3 Plugin Lifecycle
┌──────────┐ ┌────────────┐ ┌─────────────┐ ┌───────────┐ ┌──────────┐
│ Loaded │ -> │ Initialized│ -> │ Active │ -> │ Finalizing│ -> │ Unloaded │
└──────────┘ └────────────┘ └─────────────┘ └───────────┘ └──────────┘
│ │ │ │ │
↓ ↓ ↓ ↓ ↓
User uploads bfosa_plugin_info Processing bfosa_finalize Cleanup
WASM file called to validate files called called to resources
compatibility with files aggregate
streaming results
1.4 Plugin Communication
1.4.1 Memory Model
Plugins share NO direct memory with the host. All data transfer uses:
JSON serialization for metadata and small data
WASM linear memory for file content (read-only, allocated by host)
1.4.2 Host Functions (Imports Available to Plugins)
// Available host functions (imported by plugin)extern"C"{// Logging (for debugging)fnbfosa_log(message_ptr:*constu8,message_len:usize);// API version checkfnbfosa_get_api_version() -> u32;// Memory management (optional, plugin can use its own)fnbfosa_allocate(size:usize) -> *mutu8;fnbfosa_deallocate(ptr:*mutu8,size:usize);// Progress reportingfnbfosa_report_progress(current:u32,total:u32);}
2. Security Considerations
2.1 Threat Model
Threat
Description
Mitigation
Malicious Code Execution
Plugin contains harmful WASM code
WASM sandbox provides no access to DOM, network, or system APIs
Denial of Service
Plugin consumes excessive CPU/memory
Resource limits (max memory, max execution time per file)
interfacePluginResourceLimits{// Maximum memory allocation (default: 16MB)maxMemory: number;// Maximum execution time per file in ms (default: 5000ms)maxExecutionTime: number;// Maximum file size plugin will process (0 = unlimited)maxFileSize: number;// Maximum concurrent workers for plugin (default: 1)maxWorkers: number;// Allow GPU access (default: false)allowGPU: boolean;}// Enforced limitsconstDEFAULT_LIMITS: PluginResourceLimits={maxMemory: 16*1024*1024,// 16 MBmaxExecutionTime: 5000,// 5 seconds per filemaxFileSize: 100*1024*1024,// 100 MBmaxWorkers: 1,allowGPU: false,};
2.3 Plugin Validation
2.3.1 Validation Steps
interfaceValidationResult{valid: boolean;errors: string[];warnings: string[];pluginInfo?: PluginInfo;}asyncfunctionvalidatePlugin(wasmBytes: ArrayBuffer): Promise<ValidationResult>{consterrors: string[]=[];constwarnings: string[]=[];// Step 1: Validate WASM formattry{constmodule=awaitWebAssembly.compile(wasmBytes);// Check for required exportsconstrequiredExports=['bfosa_plugin_info','bfosa_process_file','bfosa_finalize','bfosa_cleanup',];for(constexpofrequiredExports){if(!WebAssembly.Module.exports(module).some(e=>e.name===exp)){errors.push(`Missing required export: ${exp}`);}}}catch(e){errors.push(`Invalid WASM format: ${e.message}`);return{valid: false, errors, warnings };}// Step 2: Initialize and query metadataconstinstance=awaitWebAssembly.instantiate(wasmBytes,{env: {bfosa_log: (msgPtr: number,msgLen: number)=>{// Capture log output for validation},// ... other host functions},});// Step 3: Check API version compatibilityconstpluginInfo=instance.exports.bfosa_plugin_info();if(!semver.satisfies(pluginInfo.api_version,CURRENT_API_VERSION)){errors.push(`Plugin requires API version ${pluginInfo.api_version}, `+`but current version is ${CURRENT_API_VERSION}`);}// Step 4: Validate resource limitsif(pluginInfo.resource_limits.max_memory>MAX_ALLOWED_MEMORY){errors.push(`Requested memory exceeds maximum: ${pluginInfo.resource_limits.max_memory}`);}// Step 5: Check for suspicious importsconstsuspiciousImports=['fetch','XMLHttpRequest','window','document'];constimports=WebAssembly.Module.imports(module);for(constimpofimports){if(suspiciousImports.includes(imp.module)){errors.push(`Suspicious import detected: ${imp.module}`);}}return{valid: errors.length===0,
errors,
warnings,
pluginInfo,};}
2.3.2 Signature Verification (Optional)
For plugin marketplace distribution, implement digital signatures:
interfaceSignedPlugin{wasmData: ArrayBuffer;signature: string;publicKey: string;}asyncfunctionverifySignedPlugin(plugin: SignedPlugin): Promise<boolean>{// Use Web Crypto API to verify signatureconstisValid=awaitcrypto.subtle.verify('RSASSA-PKCS1-v1_5',awaitcrypto.subtle.importKey('spki',base64ToArrayBuffer(plugin.publicKey),{name: 'RSASSA-PKCS1-v1_5',hash: 'SHA-256'},false,['verify']),base64ToArrayBuffer(plugin.signature),plugin.wasmData);returnisValid;}
2.4 Allowed Operations
Operation
Allowed
Notes
Read file content
Yes (controlled)
Only for user-selected files
Read file metadata
Yes
Name, size, type, last modified
Log messages
Yes
Via bfosa_log host function
Allocate memory
Yes
Within limits
Perform computations
Yes
CPU-bound operations
Access DOM
No
Not available in WASM
Network requests
No
Not available in WASM
File system write
No
Not available in WASM
Browser storage
No
Not available in WASM
3. Data Flow
3.1 End-to-End Flow
┌─────────────────────────────────────────────────────────────────────────┐
│ User Action Flow │
│ │
│ 1. User selects folder │
│ ↓ │
│ 2. User chooses plugin(s) to use (or default) │
│ ↓ │
│ 3. System traverses folder (existing Phase 1 code) │
│ ↓ │
│ 4. For each file: │
│ a. Collect metadata │
│ b. If plugin requires content: Read file │
│ c. Call plugin.bfosa_process_file(file) │
│ d. Collect plugin output │
│ e. Update progress UI │
│ ↓ │
│ 5. Call plugin.bfosa_finalize(outputs) │
│ ↓ │
│ 6. Display aggregated results │
└─────────────────────────────────────────────────────────────────────────┘
// web/e2e/plugin-flow.spec.tsimport{test,expect}from'@playwright/test';test.describe('Plugin Flow',()=>{test('upload and use plugin',async({ page })=>{awaitpage.goto('/');// Upload pluginawaitpage.click('[data-testid="plugin-upload-button"]');constfileInput=awaitpage.input('#plugin-file-input');awaitfileInput.setInputFiles('./fixtures/md5-calculator.wasm');// Verify plugin appears in listawaitexpect(page.locator('[data-testid="plugin-item-md5-calculator"]')).toBeVisible();// Select folderawaitpage.click('[data-testid="select-folder-button"]');// ... select test folder// Run analysis with pluginawaitpage.check('[data-testid="plugin-checkbox-md5-calculator"]');awaitpage.click('[data-testid="analyze-button"]');// Wait for resultsawaitexpect(page.locator('[data-testid="analysis-results"]')).toBeVisible();awaitexpect(page.locator('[data-testid="plugin-result-md5-calculator"]')).toBeVisible();});});
10. Performance Considerations
10.1 Performance Targets
Metric
Target
Measurement
Plugin load time
< 100ms
Time from upload to ready
Per-file processing
< 10ms (metadata), < 100ms (small content)
Average execution time
Memory overhead
< 50MB per active plugin
Peak WASM memory
UI responsiveness
60fps during processing
Frame time
Large file handling
Support files up to 1GB
Streaming mode
10.2 Optimization Strategies
Worker Pool: Reuse Web Workers for multiple files
Batch Processing: Process files in batches to reduce overhead
Lazy Loading: Load plugins only when needed
Memory Pooling: Reuse WASM memory allocations
Result Streaming: Send results incrementally rather than all at once
interfacePluginManager{// Load a plugin from WASM bytesloadPlugin(wasmBytes: ArrayBuffer,options?: LoadOptions): Promise<Plugin>;// Unload a pluginunloadPlugin(pluginId: string): Promise<void>;// Get all loaded pluginsgetPlugins(): Plugin[];// Get a specific plugingetPlugin(pluginId: string): Plugin|undefined;// Execute a plugin on filesexecutePlugin(pluginId: string,files: FileMetadata[],options?: ExecutionOptions): Promise<PluginExecutionResult>;// Validate a plugin before loadingvalidatePlugin(wasmBytes: ArrayBuffer): Promise<ValidationResult>;}interfaceLoadOptions{autoStart?: boolean;resourceLimits?: Partial<ResourceLimits>;}interfaceExecutionOptions{signal?: AbortSignal;onProgress?: (current: number,total: number)=>void;includeContent?: boolean;chunkSize?: number;}
12.2 Plugin Storage Service API
interfacePluginStorage{// Save plugin to IndexedDBsavePlugin(plugin: Plugin,wasmBytes: ArrayBuffer): Promise<void>;// Load plugin from IndexedDBloadPlugin(pluginId: string): Promise<Plugin|null>;// Delete plugin from IndexedDBdeletePlugin(pluginId: string): Promise<void>;// List all saved pluginslistPlugins(): Promise<PluginInfo[]>;// Check if plugin existshasPlugin(pluginId: string): Promise<boolean>;}
13. Future Enhancements
13.1 Planned Features (Phase 3+)
Feature
Description
Priority
Plugin Marketplace
Central repository for plugins
P1
Plugin Signing
Cryptographic verification of plugins
P0
Plugin Sandbox UI
Isolated preview of plugin output
P2
Plugin Chaining
Output of one plugin feeds another
P2
Plugin Templates
Scaffold new plugins quickly
P1
Visual Plugin Builder
No-code plugin creation
P3
13.2 Extension Points
Potential future extension points for plugins:
Custom Result Visualizations: Plugins can define custom UI components
Export Formats: Plugins can add export options
Filtering: Plugins can add file filtering capabilities
Notifications: Plugins can trigger notifications on conditions
14. Glossary
Term
Definition
ABI
Application Binary Interface - The contract between host and plugin
WASM
WebAssembly - Binary instruction format for the web
OPFS
Origin Private File System - Browser private file storage
Streaming
Processing data in chunks rather than loading entirely
Sandbox
Isolated execution environment with restricted capabilities
# Build a plugincd plugins/my-plugin
wasm-pack build --target web --out-dir ./pkg
# Optimize WASM size
wasm-opt ./pkg/my_plugin_bg.wasm -O4 -o ./pkg/my_plugin_bg_opt.wasm
# Test plugin locally
pnpm run test:plugin
# Package for distribution
pnpm run package:plugin
Document End
This architecture document provides the technical foundation for implementing a secure, performant, and extensible Dynamic Plugin System for the CreatorWeave. All design decisions prioritize security, user privacy, and developer experience.