The fs module provides scope-checked filesystem access: every read
and write is validated against the app's configured PathScope in the
backend and rejected when out of scope. The API has three layers — v1
convenience functions (text/directory/metadata), binary IO
(readFile/writeFile, base64 on the wire + raw IPC response),
handle-style IO (open → a FileHandle with
read/write/seek/flush/close), plus an extended stat family
(lstat/readLink/truncate/chmod) and a watch powered by real
FSEvents. Everything is backed by the plugin:fs|* commands (aligned
with @tauri-apps/plugin-fs).
Three permission sets:
| Permission set | Grants |
|---|---|
fs:default |
Read-only: read-text-file, read-dir, exists |
fs:write-default |
Read + write text, no remove (safer app default) |
fs:full |
Every operation incl. remove/copy/rename/stat |
Fine-grained permissions: fs:allow-open, fs:allow-truncate,
fs:allow-lstat, fs:allow-read-link, fs:allow-chmod,
fs:allow-read-file, fs:allow-write-file, fs:allow-read-text-file,
fs:allow-write-text-file, fs:allow-watch, fs:allow-read-dir,
fs:allow-exists, fs:allow-remove, fs:allow-make-dir,
fs:allow-copy, fs:allow-rename, fs:allow-stat (plus
fs:deny-write-text-file, which overrides allow).
From examples/hello/capabilities/main.json (the fs entries):
The scope comes from plugin construction: fsPlugin({ scope }) accepts a
PathScope config or instance (an instance can be grown dynamically by
persisted-scope). From examples/hello/src/main.ts — the fs scope is
the persisted-scope instance, baseline $TMP/**, grown with
$HOME/ztron-persisted-spike/** in the spike:
Example (adapted from the matching sections of
examples/hello/frontend/src/main.ts; the anchors FS_OK, FS_WATCH_OK,
FS_BINARY_OK, FS_COPY_RENAME_OK are its real run outputs):
ACL behavior: the frontend's section 4b asserts the denial path — the
capability grants fs:write-default but not fs:allow-remove, so
fs.remove(...) is rejected by the backend with "access denied"; the
"out-of-scope exists() reports false instead of throwing" is core's
own behavior (see the exists command in
packages/core/src/plugins/fs.ts: it returns false when
scope.tryCheck yields null), not a frontend assertion.
plugin:fs|* totals 23 commands, mapped to the API:
| Command | API |
|---|---|
read_text / write_text |
readText / writeText |
read_file / write_file |
readFile / writeFile (binary) |
read_dir / exists |
readDir / exists |
remove / make_dir |
remove / makeDir |
copy / rename / stat |
copyFile / renameFile / stat |
watch / unwatch |
watch() and its returned unwatch fn |
open / read / write / seek / flush / close |
open and the FileHandle methods |
truncate / lstat / read_link / chmod |
truncate / lstat / readLink / chmod |
Full list in the Commands Reference and the API symbol reference.
Applicable version: ztron 0.3.1