All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Plugin system (Phase 6): Dynamic loading of
.so/.dylib/.dllextensions at runtimesrc/interface/ffi/src/plugin.zig:GossamerVtable(9-function restricted API), dlopen/dlsym/dlclose lifecycle, 64-slot plugin registrygossamer_plugin_load(handle, path)→ plugin_id,gossamer_plugin_unload(plugin_id),gossamer_plugin_list()→ JSON- Each plugin exports
gossamer_plugin_init(handle, channel, vtable)and receives a restricted vtable (no GTK/WebKit internals — only eval/emit/channel_bind/cap_grant family) BindingEntry.plugin_idfield + liveness check inwebview_gtk.zigIPC dispatch path prevents use-after-free when handlers are called after plugin unloadprim__pluginLoad/prim__pluginUnload/prim__pluginListadded toForeign.idrwith safe wrappers- Linux/BSD builds now link
libdlfor dlopen support - 9 new integration tests covering null handle, empty path, nonexistent library, double-unload, idempotent unload, and empty-list JSON
- Sandboxing model: API restriction via vtable + RTLD_LOCAL (Phase 6a). Subprocess isolation (Phase 6b) deferred — plugins currently share process privileges, appropriate for developer tooling
- Integration test suite expanded: 39 → 173 tests (+134 new), covering guard mode, window registry, window groups lifecycle, z-order management, broadcast/send_to, arrange strategies, transmute, activity tracking, debug drawer, typed Groove, async IPC, platform queries, CSP module, filesystem (cap-gating + round-trip), SSG (md_to_html, template substitution, front matter/body extraction), Groove module, and cross-cutting invariants
- Package distribution recipes: Debian
.deb(dpkg-buildpackage + dh), RPM.spec(rpmbuild), Flatpak JSON manifest, macOS universal binary + DMG (lipo + hdiutil), Windows WiX 4 installer with PATH registration - Justfile packaging recipes:
package-deb,package-rpm,package-flatpak,package-macos,package-windows,package-all
- iOS screen dimensions:
webview_ios.zignow queriesUIScreen.mainScreen.boundsviaobjc_msgSendcast to*const fn → CGRect; hardcoded 390×844 replaced with real device dimensions stored inWebviewState.screen_width/height - Android JNI constructor:
registerIPCHandlerwas callingjni_CallObjectMethod(instance method) on a class reference with<init>— fundamentally wrong. Replaced withjni_NewObject(env, bridge_cls, bridge_init, native_ptr)with correctjni_NewObjectextern declaration.nativeInitnow accepts and cachesscreen_width/screen_heightparams .zig-cache/gitignore too narrow: Changed.zig-cache/(root-only) andzig-out/to**/.zig-cache/and**/zig-out/to catch nested build artifact directories (cli/.zig-cache/,src/interface/ffi/.zig-cache/, etc.)
- Cross-platform support: v0.3.0 is the cross-platform desktop release
- Windows WebView2 COM callbacks: Full async COM callback chain for WebView2 initialisation —
EnvCompletedHandlercreates environment,ControllerCompletedHandlerextracts ICoreWebView2 and sets bounds, synchronised via Windows event object with 10s timeout - Windows IPC handler:
WebMessageHandlerCOM object implementsICoreWebView2WebMessageReceivedEventHandler— receiveschrome.webview.postMessage(), dispatches to bindings map, sends responses viaExecuteScript - Platform detection query API: 6 new exported functions (
gossamer_platform,gossamer_arch,gossamer_webview_engine,gossamer_is_desktop,gossamer_platform_json) — compile-time evaluated, zero-cost, queryable from JS/Ephapax/Idris2 - Idris2 ABI declarations:
platform,arch,webviewEngine,isDesktop,platformJsonin Foreign.idr with safe wrappers - Cross-compilation Justfile recipes:
build-macos-x64,build-macos-arm,build-windows,build-linux-arm,build-linux-riscv,build-freebsd,build-all-platforms,platforms(show supported targets) - 7 new unit tests for platform detection API
- SSG docs site: 3 new pages (getting-started, ephapax-primer, platform-support)
- Updated nav template with 5 navigation links
- AWK SSG pipeline verified — all pages build from site/src/content/
- Version bumped from 0.1.0 to 0.3.0 (main.zig + build.zig)
- Windows
registerIPCHandlernow creates a real COM event handler instead of passing null - IPC JS bridge already supports all three transport paths:
webkit.messageHandlers(GTK/Cocoa),chrome.webview(Win32),GossamerBridge(Android)
- Windows WebView2 was previously stub-only (window created but no webview attached) — now performs full async initialisation via COM callbacks
- Async IPC:
gossamer_channel_bind_async()spawns callback on worker thread withg_idle_addposting response back to GTK main thread; 256-slot inflight tracker withstd.Thread.Mutex; Rust bindingapp.command_async(); ReScript already Promise-based - CSP enforcement:
gossamer_set_csp(handle, csp_string)export; CLI auto-applies CSP fromgossamer.conf.jsonsecurity.csp; Rustapp.set_csp(); ReScriptGossamer.Security.setCsp() - Streaming IPC (backend-to-frontend push):
gossamer_emit(handle, event_name, payload)export; thread-safe viag_idle_add; JSwindow.__gossamer_on(name, callback)returns unsubscribe; Rustapp.emit(name, payload); ReScriptGossamer.Event.on(name, callback) - Hot reload:
gossamer devnow watchesbuild.watch.paths(orfrontendDistfallback) for file changes and auto-reloads the webview viag_idle_add+gossamer_eval("location.reload(true)"); configurable extensions, debounce, and poll interval; separatefile_watcher.zigmodule with polling thread - 13 new unit tests (7 async IPC, 6 streaming IPC)
- Thread-local error strings: added
clearError()at top of all 16+ exported functions to prevent stale error leakage - Capability registry: improved overflow error message to specify "256 slots" limit
- Revocation set: verified FIFO eviction already correctly implemented
- Dialog allocator: verified
c_allocatorconsistency across all paths