Commit graph

163 commits

Author SHA1 Message Date
b99cc73a47
Merge pull request #1 from marcoallegretti/hardening/os-integration-and-rendering
Hardening/os integration and rendering
2026-03-13 14:34:20 +01:00
cd13f4cd3a fix(appd): combine set_state and broadcast into one lock acquisition on READY
The two consecutive registry lock acquisitions after READY left a window
where session state was Running but the AppReady broadcast had not yet
been sent. A concurrent reader winning the lock in that window would
observe Running without a corresponding event. Combining into one
acquisition closes the window.
2026-03-13 14:07:06 +01:00
e02ce5722d fix(appd,runtime): harden session lifecycle and IPC mutex safety
- supervise: in the stdout-read-error-before-READY case, immediately
  kill the child process, tear down the file portal, mark the session
  Stopped, and return; previously the function fell through to child.wait()
  leaving the session in Starting state with no guaranteed cleanup path
- supervise: restructure app_shell binding as a match expression so the
  compiler can verify the initial None value is not silently discarded
- weft-runtime: replace Mutex::lock().unwrap() with unwrap_or_else in
  the weft:app/ipc send, recv, and connect host functions so a poisoned
  mutex does not panic inside the Wasmtime host-call context
2026-03-13 14:05:31 +01:00
a098b3e93d fix(shell): harden Servo shell and app shell against rendering and lifecycle failures
- blit_software: replace expect() on softbuffer Context and Surface
  creation with log-and-skip so a frame failure does not crash the process
- blit_software: replace NonZeroU32::new(1).unwrap() with NonZeroU32::MIN
- resumed: replace create_window().expect() with a match that calls
  event_loop.exit() and returns on failure instead of unwinding
- build_rendering_ctx: return Option<RenderingCtx> instead of panicking
  when SoftwareRenderingContext creation fails; callers exit cleanly
- resumed (app-shell): exit without emitting READY when no rendering
  context is available so weft-appd observes a clean session failure
- weft-servo-shell: bound gesture forwarding to one active thread at a
  time using JoinHandle::is_finished(); excess batches are dropped with
  a debug log to prevent unbounded thread creation per event loop tick
- shell_client (both shells): replace post-ensure! unwrap() with expect()
  that documents the invariant
2026-03-13 14:01:42 +01:00
b82345d24e fix(compositor): replace panic-prone unwraps with explicit error handling in winit and DRM backends
- winit backend: client insertion and dispatch_clients failures now log
  and continue instead of unwinding the event loop
- winit backend: bind/render/submit failures in the redraw handler skip
  the frame and log a warning; the compositor stays running
- DRM backend: same client insertion and dispatch_clients treatment
- DRM device_added: use .context()? instead of unwrap() when inserting
  the new device entry after the drm field is known to be initialised
- DRM render_output: use guard-return instead of unwrap() to access drm
  state that was already verified non-None lines above
- compositor state: duplicate layer surface mapping from a misbehaving
  client logs a warning and returns instead of panicking
2026-03-13 13:56:57 +01:00
67f54c39be fix(ci): restore cross-platform and linux checks 2026-03-13 13:44:44 +01:00
a46af65e6e fix(appd): stabilize tests and unix-gate sd-notify 2026-03-13 12:52:39 +01:00
84f82fbadf fix(shell): gate servo-embed-only modules 2026-03-13 12:52:19 +01:00
fedd0e8bbf chore: ignore generated VM artifacts 2026-03-13 12:52:11 +01:00
efe1396a85 ci: install llvm for mozjs_sys builds 2026-03-13 12:51:48 +01:00
51eccc30de fix(ci): clippy lints in weft-appd, remove unused sd-notify dep, add missing apt packages 2026-03-13 10:58:40 +01:00
2beebf13d2 style: apply rustfmt to all workspace crates 2026-03-13 10:38:01 +01:00
326d4d1452 build(nix): lock flake inputs for nixos-25.05 + rust-overlay 2026-03-12 23:47:00 +01:00
4876d7a87c build(nix): set virtualisation.graphics=false for WSL2 serial console boot 2026-03-12 22:25:02 +01:00
1b24fbd2aa build(nix): use pkgs.libgbm for GBM library (mesa-libgbm is separate in nixpkgs 25.05) 2026-03-12 22:15:28 +01:00
f987f23646 build(nix): use RUSTFLAGS to pass gbm/libinput library paths to linker 2026-03-12 22:09:38 +01:00
fe077c69e1 build(nix): fix compositor link: append gbm/libinput paths to NIX_LDFLAGS via preBuild hook 2026-03-12 22:04:43 +01:00
c695b420be build(nix): add libinput to compositor inputs; set NIX_LDFLAGS for mesa/gbm and libinput 2026-03-12 22:00:27 +01:00
6c3994888d fix(compositor): replace invalid as u32 casts on wayland enum types with u32::from() 2026-03-12 21:53:57 +01:00
64f6d17b12 build(nix): add libdisplay-info to weft-compositor build inputs 2026-03-12 21:50:20 +01:00
9078d10277 build(nix): build servo-shell/app-shell as stubs in Nix VM image
servo WebIDL Python codegen is incompatible with Nix hermetic sandbox.
Build weft-servo-shell and weft-app-shell without servo-embed feature
so the VM infrastructure compiles cleanly. The full servo-embed build
is performed separately via cargo on a Linux host.
2026-03-12 21:47:45 +01:00
f0c061a054 build(nix): add llvm and nasm to servo packages native build inputs for mozjs_sys 2026-03-12 21:39:39 +01:00
222c7db151 build(nix): add fontconfig to servo-shell and app-shell build inputs 2026-03-12 21:34:20 +01:00
294bd163b9 build(nix): use Rust 1.93.0 via rust-overlay for all package builds
Add oxalica/rust-overlay flake input; override rustPlatform in
weft-packages.nix with cargo/rustc from rust-bin.stable.1.93.0;
apply overlay in both devShell and nixosConfigurations.weft-vm.
Fixes build failure where nixos-25.05 Rust 1.86.0 was below the
rust-version requirement of wasmtime and other dependencies.
2026-03-12 21:28:14 +01:00
f6cefeeccc build(nix): switch to nixos-25.05 for Rust 1.87 edition2024 support 2026-03-12 21:19:11 +01:00
c09602646f build(nix): replace libseat with seatd (renamed in nixpkgs 24.11) 2026-03-12 21:09:02 +01:00
b0f208eba7 build(nix): add servo-shell/app-shell packages, real git hashes, fix VM configuration
- weft-packages.nix: add weft-servo-shell and weft-app-shell with servo-embed
  feature; real sha256 hashes for servo (8e7dc40) and stylo (dca3934) git deps
  computed via nix-prefetch-git; add clang/cmake/python3 as native build inputs
  for servo packages; set LIBCLANG_PATH; disable doCheck for VM builds
- configuration.nix: import virtualisation/qemu-vm.nix for system.build.vm;
  replace hardware.opengl with hardware.graphics (NixOS 24.11); add
  weft-servo-shell systemd user service; add servo-shell/app-shell/pack to
  environment packages
- infra/vm/build.sh: switch to system.build.vm target (qcow2 attribute not
  provided by default NixOS modules)
- infra/vm/run.sh: invoke the VM script produced by system.build.vm
2026-03-12 21:07:39 +01:00
2ae05312dc docs: correct openSUSE package names verified against rpmfind
- Replace Mesa-libEGL-devel and Mesa-libGLES-devel (do not exist on
  openSUSE) with libglvnd-devel (Khronos EGL/GLES dispatch headers)
- Replace libseat-devel (does not exist on openSUSE) with seatd-devel

Package names confirmed via rpmfind.net against Tumbleweed and Leap
repositories.
2026-03-12 20:52:34 +01:00
7b4dbcdaf6 docs: replace apt-get/Debian package references with openSUSE/zypper
- README.md: zypper install with openSUSE package names
- docs/building.md: zypper install with openSUSE package names
- crates/weft-servo-shell/SERVO_PIN.md: openSUSE package names,
  remove Fedora/RHEL note
2026-03-12 20:48:17 +01:00
0b26c2e548 docs: remove internal tracking labels from all public documentation
- README.md: remove internal tracking labels; replace with plain
  English descriptions
- docs/security.md: rename section heading, remove tracking reference
- crates/weft-servo-shell/SERVO_PIN.md: replace tracking labels with
  descriptive headings; rename section to Known limitations
2026-03-12 20:45:56 +01:00
379d0886bd fix(appd): set WEFT_DISABLE_CGROUP in supervisor test
In environments where XDG_RUNTIME_DIR/systemd/private exists but the
user systemd session is not functional, systemd_cgroup_available()
returns true and the test script is wrapped with systemd-run, which
fails immediately, causing ChildStdout to return EOF before READY.

Set WEFT_DISABLE_CGROUP=1 for the duration of the test and restore
it on exit.
2026-03-12 20:16:58 +01:00
54b5fb662b fix(runtime): update for wasmtime-wasi 30 and fix seccomp filter
- IoView/WasiView split: implement IoView for State, remove table()
  from WasiView impl
- preopened_dir: new signature takes host path and guest path directly
- LinkerInstance::func_wrap returns Result in wasmtime 30; use a
  variable for the clipboard LinkerInstance
- Set PR_SET_NO_NEW_PRIVS before applying the seccomp filter
- Unconditional syscall block uses empty Vec<SeccompRule>
2026-03-12 20:03:33 +01:00
e3504c324b feat(infra): NixOS VM config, CI type-check job, documentation
- flake.nix, infra/nixos/: NixOS VM with Mesa, virtio-gpu, Wayland,
  systemd user services for compositor and session supervisor
- infra/vm/: QEMU build and run scripts
- .github/workflows/ci.yml: add Linux job to type-check weft-servo-shell
  and weft-app-shell with --features servo-embed
- docs/architecture.md, docs/security.md, docs/building.md: replace
  stale pre-implementation design documents
- README.md: rewrite to reflect current codebase
- crates/weft-servo-shell/SERVO_PIN.md: update implementation status and add
  SpiderMonkey process boundary statement
2026-03-12 20:03:25 +01:00
794f6c2225 feat(examples): add counter and notes demo apps
- examples/org.weft.demo.counter: stateless counter Wasm component
  using weft:app/ipc for increment/decrement/reset; built for
  wasm32-wasip2 with wit-bindgen 0.53; dark-themed HTML UI
- examples/org.weft.demo.notes: persistent notes Wasm component
  using weft:app/ipc + WASI preopened /data dir (fs:rw:app-data);
  save/load via newline-delimited IPC protocol; HTML textarea UI
- examples/keys/: committed demo Ed25519 keypair; both packages
  signed with weft-pack sign
- workspace Cargo.toml: exclude examples from workspace members
  (they target wasm32-wasip2, not the host toolchain)
- SERVO_PIN.md: update deps section and document shell-client display sharing resolved in
  full description of connect_with_display implementation
2026-03-12 15:31:20 +01:00
34359acf3f feat(servo-embed): wire Servo deps and share Wayland surface with shell client
- Add servo/winit/softbuffer as optional deps in weft-servo-shell and
  weft-app-shell Cargo.toml, gated on servo-embed feature
- Replace ShellClient::connect() and connect_as_app() with
  connect_with_display() and connect_as_app_with_display(), using
  Backend::from_foreign_display to share the winit wl_display connection
- Move ShellClient construction into resumed() in both embedders after
  winit window and wl_surface are available
- Pass actual wl_surface to create_window instead of None
- Fix pre-existing field name bug: wayland-scanner generates _type for
  the reserved keyword arg name=type, not r#type
2026-03-12 15:16:17 +01:00
4edfa00e22 feat(runtime): sys:clipboard host functions via wl-paste/wl-copy 2026-03-12 12:59:24 +01:00
91eb7cb823 fix: gate host_fetch and host_notify on wasmtime-runtime feature; suppress dead_code on resolve_weft_system_url 2026-03-12 12:52:55 +01:00
4d0089a107 feat: appd IPC relay, WIT interfaces, UI kit, gesture routing, and CI hardening
- weft-appd: per-session IPC socket paths; bidirectional Wasm-HTML JSON relay
  via spawn_ipc_relay; SO_PEERCRED UID check on Unix socket connections;
  PanelGesture request and NavigationGesture broadcast for compositor gestures
- weft-runtime: weft:app/ipc, weft:app/fetch, weft:app/notifications WIT
  interfaces; IpcState non-blocking Unix socket host functions; ureq-backed
  net:fetch host function (net-fetch feature); notify-send notifications host
- weft-file-portal: spawn a thread per accepted connection for concurrent access
- weft-app-shell: weft-system:// URL translation; WEFT UI Kit UserScript
  injection; resolve_weft_system_url helper
- weft-servo-shell: forward compositor navigation gestures to weft-appd
  WebSocket as PanelGesture; WEFT UI Kit UserScript injection
- infra/shell: weft-ui-kit.js with 11 custom elements (weft-button, weft-card,
  weft-dialog, weft-icon, weft-list, weft-list-item, weft-menu, weft-menu-item,
  weft-progress, weft-input, weft-label); system-ui.html handles
  NAVIGATION_GESTURE messages and dispatches weft:navigation-gesture CustomEvent
- infra/systemd: add missing env vars to weft-appd.service; correct
  servo-shell.service binary path and system-ui.html argument
- .github/workflows/ci.yml: exclude weft-servo-shell and weft-app-shell from
  cross-platform job; add them to linux-only job with libsystemd-dev dependency
2026-03-12 12:49:45 +01:00
a401510b88 feat(appd): per-app process isolation via weft-app-shell
Add weft-app-shell binary: takes <app_id> <session_id> args, connects to
zweft_shell_manager_v1 as an application window, resolves the app UI URL,
and runs a single Servo WebView in an isolated process. Prints READY to
stdout after the window is initialised so weft-appd can track the session
lifecycle.

weft-appd runtime.rs: after weft-runtime emits READY, spawn weft-app-shell
(WEFT_APP_SHELL_BIN env var) alongside it. The app shell is killed when the
session ends via abort or natural runtime exit.

weft-servo-shell: remove in-process app WebView management. The shell now
manages the system UI WebView only; all app rendering happens in dedicated
weft-app-shell processes.
2026-03-12 10:58:45 +01:00
3ee2f283d8 feat(servo-shell): dispatch shell client event queue in servo event loop
Wire ShellClient into App so its Wayland event queue is dispatched each
frame via about_to_wait. This ensures configure, focus_changed, and
window_closed events from the compositor are processed. window_closed
now triggers a clean Servo shutdown.

The EGL rendering path (WindowRenderingContext + surfman eglSwapBuffers)
produces frames transparently via Mesa DMA-BUF buffer sharing; no
explicit zwp_linux_dmabuf_v1 code is required in the shell.

Remaining: ZweftShellWindowV1 is created with surface=null; sharing the
winit wl_surface with the shell client connection is not currently
feasible without refactoring to a single shared Wayland connection.
2026-03-11 20:46:53 +01:00
c244a58844 docs(servo-shell): mark backdrop-filter as resolved in SERVO_PIN.md
backdrop-filter is fully implemented across two commits:
- marcoallegretti/stylo servo-weft f1ba496: enables backdrop-filter parsing
- marcoallegretti/servo servo-weft 8e7dc40: wires stacking context and display list
2026-03-11 20:26:02 +01:00
d5be48ad2d docs(servo-shell): document backdrop-filter implementation plan and stylo fork workflow
- CSS Grid is implemented via Taffy; backdrop-filter is the remaining unimplemented property
- Document the two-step implementation: stylo parsing enable + display list wiring
- Add Stylo fork section with patch template and step-by-step instructions
- Expand per-app process isolation section with clearer implementation detail
2026-03-11 19:45:39 +01:00
ab70a858f9 docs(servo-shell): point Servo dep at marcoallegretti/servo servo-weft branch
Fork: https://github.com/marcoallegretti/servo
Branch: servo-weft
Base rev: 04ca254f843ed650d3e5b14e5693ad51a60cc84b (upstream main 2026-03-11)

Update the Cargo snippet and update policy to match the fork-and-PR workflow.
2026-03-11 19:38:45 +01:00
a3f60910d5 fix(appd): remove abort_sender on READY timeout early-return path
The READY timeout branch killed the process and returned Ok(()) without
calling remove_abort_sender(), leaving a spent entry in abort_senders.
Add the call to keep it consistent with all other exit paths.
2026-03-11 19:01:59 +01:00
8eace960c2 fix(file-portal): block dotdot path-traversal in is_allowed
Path::starts_with is component-aware but does not resolve .., so
/allowed/../etc/passwd would pass the check. Add normalize_path() that
lexically resolves . and .. components without touching the filesystem
so the check works on non-existent paths too. Add regression test.
2026-03-11 18:54:25 +01:00
a18f5c7604 fix(file-portal): create parent directories on write
std::fs::write fails when the destination parent does not exist.
Add create_dir_all before the write so apps can store files in
nested paths (e.g. config/sub/settings.json) without pre-creating
directories. Add regression test for the nested-path case.
2026-03-11 18:52:54 +01:00
a5846c1317 test(appd): verify session transitions to Stopped when WEFT_RUNTIME_BIN absent 2026-03-11 18:47:29 +01:00
0fea8f58e4 fix(appd): mark session Stopped when WEFT_RUNTIME_BIN is absent
Previously the supervisor returned Ok(()) without updating the session
state, leaving it in Starting indefinitely. Now it sets state to
Stopped, removes the abort sender, and broadcasts AppState:stopped
before returning, consistent with every other early-exit path.
2026-03-11 18:43:16 +01:00
099283bc4b feat(servo-shell): sync WebView set on appd reconnect via SyncSessions
RUNNING_APPS response now produces a SyncSessions command instead of
individual Launch commands. The embedder retains only WebViews whose
session_id is in the active list (removes stale entries from sessions
that stopped during a disconnect), then creates WebViews for any
sessions not yet tracked. This is idempotent thanks to the existing
contains_key guard in create_app_webview.
2026-03-11 18:41:00 +01:00
6f43490192 fix(appd): remove abort_sender entry when session supervisor exits
When a runtime process exits naturally (not via TerminateApp) the
oneshot Sender remained in abort_senders until shutdown_all().
Add remove_abort_sender() and call it at the normal exit path in
supervise() to release the entry immediately.
2026-03-11 18:38:35 +01:00