Commit graph

117 commits

Author SHA1 Message Date
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
4445b57a7c fix(appd): downgrade WS parse failure from warn to debug
App-level weftIpc messages from the system UI routinely fail Request
deserialization since they are not system commands. Using warn generates
log noise during normal operation.
2026-03-11 18:36:32 +01:00
52e9a0a503 test(pack): capability validation tests for check subcommand 2026-03-11 18:35:07 +01:00
bd348e0c3d feat(pack): validate capability strings in check subcommand
check_package() now rejects any capabilities not in the known set:
  fs:rw:app-data, fs:read:app-data,
  fs:rw:xdg-documents, fs:read:xdg-documents

This keeps the manifest in sync with what resolve_preopens() in
weft-appd actually maps; unknown strings would otherwise silently
produce no preopens at runtime.
2026-03-11 18:33:05 +01:00
c9e1eb5075 fix(servo-shell): guard create_app_webview against duplicate session_id
A broadcast LaunchAck can arrive in addition to any direct response,
causing create_app_webview to be called twice for the same session.
Without the guard the second call silently overwrites the existing
WebView entry without destroying it. Early-return if the session is
already tracked.
2026-03-11 18:31:35 +01:00
9448cc5140 test(appd): assert LaunchAck is broadcast as well as returned directly 2026-03-11 18:28:59 +01:00
55b80ea2b3 fix(appd): broadcast LaunchAck to all WebSocket clients on app launch
Previously LaunchAck was sent only as a direct response to the
requesting connection. The servo-shell appd_ws listener thread is a
separate WebSocket connection and would never receive LaunchAck for
UI-initiated launches, causing those sessions to have no WebView.

Now dispatch() broadcasts LaunchAck over the registry broadcast channel
immediately after returning the direct response, so all connected
WebSocket clients (including the shell listener) learn about every new
session regardless of which connection triggered the launch.
2026-03-11 18:27:56 +01:00
dde4a1dffb feat(servo-shell): reconnect appd WebSocket with exponential backoff
run_listener() now loops forever instead of returning on first failure.
Connect errors retry starting at 500ms, doubling up to 16s.
On disconnect the inner loop breaks and the outer loop reconnects
after the current backoff delay, then resets backoff to 500ms.
QUERY_RUNNING is sent again on each reconnect to re-sync session state.
2026-03-11 18:24:54 +01:00
c181bc8015 feat(runtime): forward WEFT_FILE_PORTAL_SOCKET into WASI environment
When WEFT_FILE_PORTAL_SOCKET is present in the process environment
(set by weft-appd before exec), it is now forwarded into the WASI
context so the WASM component can read it via std::env::var or
equivalent and locate the per-session file portal socket.
2026-03-11 18:23:32 +01:00
8eb7211998 refactor(appd): consolidate portal cleanup through kill_portal in normal exit path 2026-03-11 18:21:43 +01:00
0877bd970d fix(appd): kill file portal process on all early-return paths in supervise()
Runtime spawn failure, READY timeout, and abort-during-startup all
previously returned without killing the portal child process or removing
its socket file. Extracted kill_portal() to consolidate cleanup and
call it in each of those three paths.
2026-03-11 18:20:16 +01:00
aa95be6244 docs(servo-shell): document EGL rendering path in SERVO_PIN.md 2026-03-11 18:18:37 +01:00
cd876b49b0 test(appd): session persistence save/load roundtrip tests
Three tests covering the save_session / load_session helpers:
- session_save_load_roundtrip: full write-then-read cycle verifying
  content, and that a second load returns None (file deleted).
- session_save_empty_load_returns_empty_vec: edge case of empty list.
- load_session_no_file_returns_none: missing file returns None.

Also fixes save_session to create_dir_all on the parent directory
before writing, which was the root cause of test failures.
2026-03-11 18:16:37 +01:00
5061310d63 feat(appd): session persistence across clean restarts
On clean shutdown (SIGINT/SIGTERM), save the list of running app IDs to
/weft/last-session.json before calling shutdown_all().

On the next startup, load_session() reads and immediately deletes that
file, then dispatches a LaunchApp for each saved app ID. This restores
the previous session after a system restart or orderly service stop.

If the file does not exist (crash, first boot, or deliberate reset) no
auto-launch occurs. Duplicate detection relies on the existing fact that
the saved processes are gone before appd starts again.
2026-03-11 18:12:38 +01:00
92920984bd feat(appd): auto-launch weft-file-portal per session
spawn_file_portal() checks WEFT_FILE_PORTAL_BIN; if set, creates a
per-session Unix socket at /weft/portal-<id>.sock and
spawns weft-file-portal with --allow args derived from the same host
paths that resolve_preopens() produces for the session.

WEFT_FILE_PORTAL_SOCKET is added to the runtime environment so
weft-runtime (and the WASM app) can locate the socket.

The portal process is killed and the socket cleaned up at the end of
supervise(), after the runtime exits and the mount is torn down.

When WEFT_FILE_PORTAL_BIN is unset the behaviour is unchanged.
2026-03-11 18:09:38 +01:00
c15fe600fc feat(servo-shell): add EGL rendering context behind servo-embed feature gate
Add RenderingCtx enum wrapping SoftwareRenderingContext or
WindowRenderingContext. build_rendering_ctx() checks WEFT_EGL_RENDERING
at startup: if set, attempts WindowRenderingContext::new with the winit
display/window handles and falls back to software on error.

render_frame() dispatches on the variant: software path blits pixels
through softbuffer; EGL path is a no-op (Servo presents directly to
the EGL surface). All WebViewBuilder calls now use RenderingCtx::as_dyn()
to produce Rc<dyn RenderingContext>.

The software path is unchanged. The EGL path is gated behind
WEFT_EGL_RENDERING and only activates with the servo-embed feature.
2026-03-11 18:06:02 +01:00
dba7916645 docs(servo-shell): mark keyboard input as resolved in SERVO_PIN.md 2026-03-11 18:01:40 +01:00
ed5a69bb74 feat(servo-shell): per-app WebView lifecycle driven by appd events (servo-embed only)
Task 10 -- App WebView lifecycle.

appd_ws module (servo-embed gated):
  Background thread connects to the appd WebSocket on startup.
  Sends QUERY_RUNNING to receive initial running sessions.
  Translates LAUNCH_ACK -> AppdCmd::Launch and APP_STATE stopped
  -> AppdCmd::Stop, then wakes the winit event loop via the
  shared EventLoopWaker.

embedder changes:
  App struct gains app_rx (mpsc receiver), app_webviews
  (HashMap<session_id, WebView>), active_session, and a stored
  rendering_context used when creating app WebViews later.

  create_app_webview(): resolves weft-app://<app_id>/index.html
  to a file URL, creates a dedicated UserContentManager with the
  weftIpc bridge injected (includes window.weftSessionId), builds
  and registers a new WebView.

  about_to_wait() drains app_rx: creates WebViews for Launch
  commands, removes and clears active_session for Stop commands.

  active_webview() returns the active-session WebView when one
  exists, falling back to the system-ui WebView. Rendering,
  keyboard, and mouse events all route through active_webview().

  Resize propagates to both the system WebView and all app WebViews.

  run() creates the mpsc channel and spawns the appd listener
  before entering the winit event loop.
2026-03-11 17:59:12 +01:00
b4824aa8d4 feat(servo-shell): input forwarding, weft-app URL resolution, weftIpc JS bridge (servo-embed only) 2026-03-11 17:52:37 +01:00
1b93f1c825 feat: weft-file-portal -- sandboxed file access broker
New crate. Per-session file proxy that gates filesystem access to an
explicit allowlist of paths passed at startup.

Usage: weft-file-portal <socket_path> [--allow <path>]...

Listens on a Unix domain socket. Each connection receives newline-
delimited JSON requests and returns newline-delimited JSON responses.
File content is base64-encoded. Operations: read, write, list.
Empty allowlist rejects all requests; paths checked with starts_with.

7 unit tests covering access control, read/write roundtrip, and list.
2026-03-11 15:52:33 +01:00
7e92b72a93 feat(pack): install accepts .app.tar.zst archives directly
install_package_to detects .app.tar.zst input by extension, unbundles
to a temp directory, derives the app_id from the archive filename stem,
then proceeds with the standard check + copy install path.

Directory-based installs are unchanged.

Test: install_package_from_archive.
2026-03-11 15:49:34 +01:00
d2cb693c55 feat(appd): MountOrchestrator -- EROFS+dm-verity image mount on app launch
Add crates/weft-appd/src/mount.rs with MountOrchestrator.

On each app launch, supervise() calls MountOrchestrator::mount_if_needed
which looks for <app_id>.app.img, <app_id>.hash, and <app_id>.roothash
in the app store roots. If all three exist and weft-mount-helper is
available (WEFT_MOUNT_HELPER env or /usr/lib/weft/ default paths), it:

  - creates /tmp/weft-mnt-<session_id>/<app_id>/
  - invokes weft-mount-helper mount to set up dm-verity and EROFS mount
  - sets WEFT_APP_STORE=/tmp/weft-mnt-<session_id> in the child env so
    the runtime resolves the package from the mounted read-only image

After the process exits, umount() invokes weft-mount-helper umount and
removes the temporary directory.

Falls back to directory-based install silently if no image is found,
mount-helper is absent, or the mount fails.

Test: find_image_returns_none_when_absent.
2026-03-11 15:47:23 +01:00
97ea969075 feat: weft-mount-helper -- setuid helper for EROFS+dm-verity mounts
New crate: weft-mount-helper. A privileged helper binary that sets up
dm-verity devices and mounts EROFS images for app isolation.

Commands:
  mount <img> <hash_dev> <root_hash> <mountpoint>
    - opens a named dm-verity device via veritysetup open
    - mounts the resulting /dev/mapper/<name> as EROFS read-only
    - cleans up the dm device if mount fails
  umount <mountpoint>
    - unmounts the mountpoint
    - closes the dm-verity device via veritysetup close

Device naming: derives a stable name from the mountpoint path, limited
to 31 chars (DM limit), always prefixed weft-. Root check reads
/proc/self/status euid rather than using unsafe libc calls.

Tests: device_name_sanitizes_path, device_name_truncates_long_paths.
2026-03-11 15:43:59 +01:00
add4d92945 feat(pack): build-image and build-verity subcommands
build-image <dir> [--out <img>]: creates an EROFS image by invoking
mkfs.erofs. Output filename defaults to <app_id>.app.img. Fails if
the output file already exists or mkfs.erofs is unavailable.

build-verity <img> [--out <hash>]: creates a dm-verity hash tree by
invoking veritysetup format. Writes the hash device to <stem>.hash
(or --out path). Extracts the root hash from veritysetup output and
writes it to <img>.roothash. Fails if veritysetup is unavailable.

Both subcommands shell out to external tools (erofs-utils and
cryptsetup-bin respectively) and return an error with an installation
hint if the binary is not found.
2026-03-11 15:39:18 +01:00
12fa53a585 feat(pack): bundle and unbundle subcommands for dist packaging
Add bundle <dir> [--out <dir>] and unbundle <archive> [--out <dir>]
subcommands to weft-pack.

bundle: validates the package, reads app_id from wapp.toml, writes
<app_id>.app.tar.zst to the output directory (default: current dir).
Archive root is <app_id>/ so extraction reproduces the package directory.
Fails if the archive already exists.

unbundle: decompresses and extracts a .app.tar.zst into the output
directory (default: current dir).

Compression level 0 (zstd default). No symlinks followed.
Dependencies added: tar 0.4, zstd 0.13.
Test: bundle_and_unbundle_roundtrip.
2026-03-11 15:37:53 +01:00
98a21da734 feat(runtime): seccomp blocklist filter via optional seccomp feature
Add seccomp feature flag (seccompiler + libc, Linux-only, optional).

When compiled with --features seccomp, weft-runtime installs a
SECCOMP_MODE_FILTER immediately after argument parsing, before any
package resolution or WASM execution.

Filter strategy: default-allow with explicit KillProcess rules for
high-risk syscalls a WASM runtime process has no legitimate need for:
ptrace, process_vm_readv/writev, kexec_load, personality, syslog,
reboot, mount/umount2, setuid/setgid/setreuid/setregid/setresuid/
setresgid, chroot, pivot_root, init_module/finit_module/delete_module,
bpf, perf_event_open, acct.

The feature is off by default so the standard build and tests are
unaffected. Enable in production service builds with --features seccomp.
2026-03-11 15:34:21 +01:00
ec4cc272af feat(pack): Ed25519 package signing -- generate-key, sign, verify subcommands 2026-03-11 15:29:49 +01:00
71b7bdf657 feat(appd): wrap runtime in systemd-run cgroup scope when user session is active
supervise() checks /systemd/private to detect an active
user systemd session. When present (and WEFT_DISABLE_CGROUP is unset),
the runtime binary is launched via:

  systemd-run --user --scope --wait --collect --slice=weft-apps.slice     -p CPUQuota=200% -p MemoryMax=512M -- <bin> ...

This places each app in a transient weft-apps.slice scope with default
resource limits from the blueprint. The --wait flag keeps systemd-run
alive so child.wait()/child.kill() remain correct.

When no user session is present the command is built directly as before.
WEFT_DISABLE_CGROUP=1 bypasses the wrapping unconditionally.
2026-03-11 15:25:04 +01:00
c5a47a05b4 feat(appd,pack): capability dispatch -- map wapp.toml capabilities to --preopen args
Add capabilities field to weft-pack PackageMeta (optional Vec<String>).
Print cap: lines in weft-pack info output when capabilities are declared.

In weft-appd:
- Make app_store_roots pub(crate) so runtime.rs can use it.
- Add resolve_preopens(app_id) in runtime.rs: reads wapp.toml from the
  package store, extracts capabilities, maps each to a (host, guest) pair:
    fs:rw:app-data / fs:read:app-data -> ~/.local/share/weft/apps/<id>/data :: /data
    fs:rw:xdg-documents / fs:read:xdg-documents -> ~/Documents :: /xdg/documents
  Unknown capabilities are logged at debug level and skipped.
- supervise() calls resolve_preopens() and appends --preopen HOST::GUEST
  flags before spawning the runtime binary.
2026-03-11 15:20:51 +01:00
84eb39db96 feat(runtime): add weft:app/notify WIT package and notify-ready host interface
Adds crates/weft-runtime/wit/weft-app.wit defining package weft:app@0.1.0
with interface notify { ready: func() }.

In the wasmtime-runtime path:
- Registers weft:app/notify@0.1.0 in the component linker before instantiation
- ready() prints
2026-03-11 15:15:11 +01:00
b2ac279dc5 feat(runtime): add --preopen and --ipc-socket CLI arguments
weft-runtime now parses optional flags after <app_id> <session_id>:
  --preopen HOST::GUEST  pre-opens a host directory at GUEST path in the
                         WASI filesystem (HOST::GUEST or HOST for same path)
  --ipc-socket PATH      sets WEFT_IPC_SOCKET env var inside the component

wasmtime-runtime path applies preopened dirs via cap_std and WasiCtxBuilder,
and injects WEFT_IPC_SOCKET when --ipc-socket is present. Stub path ignores
both flags.

weft-appd: SessionRegistry gains ipc_socket field (set to the appd Unix
socket path in run()), extracted alongside compositor_tx in dispatch(), and
forwarded to supervise() as ipc_socket_path. supervise() passes
--ipc-socket <path> to the spawned runtime when present.

cap-std added as optional dep under wasmtime-runtime feature.
2026-03-11 15:10:11 +01:00