03 · File Operations
A tiny append-only “database”: each run reads data.json, adds an item, and
writes it back. The read and write grants cover exactly one file.
Source: examples/03-file-ops
Run
cd examples/03-file-ops
3va run app.js --allow-read=./data.json --allow-write=./data.jsonFirst run (no data.json yet):
No data.json found, starting fresh
Wrote 1 items to data.json
All items:
#1: Item created at 2026-09-24T23:17:41.046ZRun it again and the items pile up:
Loaded 1 items from data.json
Wrote 2 items to data.jsonHow it works
const DATA_FILE = path.join(__dirname, "data.json");
if (fs.existsSync(DATA_FILE)) {
items = JSON.parse(fs.readFileSync(DATA_FILE, "utf-8"));
}
// …push a new item…
fs.writeFileSync(DATA_FILE, JSON.stringify(items, null, 2));3va resolves ./data.json in the flag to an absolute path and checks each
fs call against it. Any other path, like ../secrets or /etc/passwd, is
still denied.
What each missing flag does
| Flags | Result |
|---|---|
none, data.json exists | exits 1: Permission denied: --allow-read=…/data.json is required |
none, no data.json | prints starting fresh, then exits 1 on the write |
--allow-read only | loads the items, then exits 1: --allow-write=…/data.json is required |
| both | works |
The error names the exact absolute path to grant, so you can copy it into the command.
Things to keep in mind
-
Grants are checked per call, so a script can fail halfway through. With only
--allow-read, the read succeeds and the write fails. Design scripts so that a denied write can’t leave data half-written. -
Scope to the file, not the directory, when you can.
--allow-write=.would also let the script overwriteapp.js. -
Relative flag paths are resolved against your current directory, while the script resolves
data.jsonagainst__dirname. Run from the example folder, or pass absolute paths in the flags. -
Find the minimum set automatically:
3va permissions learn app.jsEquivalent CLI flags: 3va run app.js --allow-read=./data.json --allow-write=./data.json --allow-env=CLUSTER_WORKER,NODE_ENVlearnruns the script with every permission, so it really writesdata.json. The two env vars it reports are read by the runtime’s own Node compatibility layer, not byapp.js. The script works without them.