Skip to Content
Examples03 · File Operations

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.json

First 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.046Z

Run it again and the items pile up:

Loaded 1 items from data.json Wrote 2 items to data.json

How it works

app.js
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

FlagsResult
none, data.json existsexits 1: Permission denied: --allow-read=…/data.json is required
none, no data.jsonprints starting fresh, then exits 1 on the write
--allow-read onlyloads the items, then exits 1: --allow-write=…/data.json is required
bothworks

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 overwrite app.js.

  • Relative flag paths are resolved against your current directory, while the script resolves data.json against __dirname. Run from the example folder, or pass absolute paths in the flags.

  • Find the minimum set automatically:

    3va permissions learn app.js
    Equivalent CLI flags: 3va run app.js --allow-read=./data.json --allow-write=./data.json --allow-env=CLUSTER_WORKER,NODE_ENV

    learn runs the script with every permission, so it really writes data.json. The two env vars it reports are read by the runtime’s own Node compatibility layer, not by app.js. The script works without them.