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.
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.
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.
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.
Two new tests mirror the weft-runtime package_store_roots tests:
- list_installed_roots_uses_weft_app_store_when_set
- list_installed_roots_includes_system_path
wsl-test.sh: add --test-threads=1 for weft-pack to prevent
WEFT_APP_STORE env var races between install, uninstall, and the
new list_roots tests.
list_installed_roots() searches WEFT_APP_STORE, then
~/.local/share/weft/apps, then /usr/share/weft/apps (same
priority order as weft-runtime and weft-appd). list_installed()
deduplicates by app_id (first root wins), sorts alphabetically within
each root, and prints id/name/version per line. Prints 'no packages
installed' when the store is empty or absent.
check_package now reads the first 4 bytes of runtime.module and rejects
files that do not begin with the Wasm magic number (0x00 0x61 0x73 0x6D).
An unreadable or too-short file is treated as invalid.
is_wasm_module(path): opens the file, reads 4 bytes, compares to MAGIC.
Test added: check_package_bad_wasm_magic - writes NOT_WASM to app.wasm,
asserts check fails with a message containing bad magic bytes.
weft-pack:
- uninstall <app_id>: validates app ID, resolves store root, removes
the installed package directory. Fails with an error if the package
is not present or the app ID is malformed.
- Extracted install_package_to(dir, root) and
uninstall_package_from(app_id, root) inner functions so tests can
drive them directly without touching process env vars (avoids parallel
test env-var races).
- install_package / uninstall_package remain the CLI-facing wrappers
that call resolve_install_root().
Tests added (2):
- install_package_copies_to_store: writes a valid temp package, calls
install_package_to, verifies all files are present, confirms a second
install fails.
- uninstall_package_removes_directory: installs then uninstalls,
verifies directory is removed, confirms a second uninstall fails.
Both tests use process-ID-derived paths to avoid cross-test collisions.
weft-pack:
- install <dir>: validates the package (runs check), resolves the user
app store root (WEFT_APP_STORE > ~/.local/share/weft/apps), copies
the package directory to <root>/<app_id>/. Fails if the destination
already exists.
- resolve_install_root(): replaces the unused _resolve_store_roots;
returns a single writable root rather than a search list.
- copy_dir(): recursive directory copy using std::fs only; no new deps.
- Updated usage text to include all three subcommands.
weft-servo-shell: removed stale implementation-note comment from
embed_servo stub.
New crate: weft-pack — command-line tool for validating WEFT application
package directories against the app-package-format spec.
src/main.rs:
- check <dir>: loads wapp.toml, validates app ID format, verifies
package.name is non-empty and <=64 chars, confirms runtime.module and
ui.entry files exist. Prints 'OK' on success or the list of errors.
- info <dir>: prints all manifest fields to stdout.
- load_manifest(): reads and parses wapp.toml with toml crate.
- is_valid_app_id(): enforces reverse-domain convention (>=3 components,
each starting with a lowercase letter, digits allowed, no hyphens or
uppercase).
Tests (5):
- app_id_valid: accepts well-formed reverse-domain IDs.
- app_id_invalid: rejects two-component, uppercase, hyphen, empty IDs.
- check_package_missing_manifest: error when wapp.toml is absent.
- check_package_valid: full happy-path with real temp files.
- check_package_invalid_app_id: error on a hyphenated app ID.
New deps: toml 0.8, serde 1 (derive).
Added weft-pack to workspace Cargo.toml; wsl-test.sh extended.