A least-authority I/O library for JavaScript.
npm install @agoric/pola-io
WIP WIP WIP - EXAMPLES BELOW ARE BROKEN
agoric run
as npx
subcommandimport { makeCmdRunner } from '@agoric/pola-io';
import { execFile as execFileNode } from 'node:child_process';
import { promisify } from 'node:util';
export const main = async ({ execFile = promisify(execFileNode) }) => {
const npx = makeCmdRunner('npx', { execFile }); // TODO --no-install
return miscTask(npx);
};
const miscTask = async npx => {
const agoric = npx.subCommand('agoric');
const { stdout } = await agoric.subCommand('run').exec(['builder.js']);
return stdout.split('\n');
};
import { makeFileRW } from '@agoric/pola-io';
import * as fsp from 'node:fs/promises';
const file = makeFileRW('/', { fsp });
const readonly = file.readOnly();
await readonly.readText(); // Allowed
// @ts-expect-error static error
await readonly.writeText();
The @agoric/pola-io
package facilitates using the Principle of Least Authority (POLA) for I/O, applying object-capability (ocap) principles to common file, network, and shell operations:
ambient/cmd.js
) exist, but are clearly labeled and should be used with care.Traditional I/O libraries often assume broad access: open any file, connect to any host, run any command. But this creates fragile systems—where one misused reference or library can do serious harm.
@agoric/pola-io
takes a different approach. Every I/O action starts from a scoped authority—an object that grants only a narrow, intended power. For example, a command runner that can execute only a given binary, or a file handle that supports only reading.
By making these boundaries explicit, we reduce how much code needs to be trusted—while still making it easy to delegate, revoke, and wrap access. This is what lets us cooperate safely: code can use what it’s been given, but nothing more.
This package builds on a long tradition of work in object-capability security and least-authority design:
std
, providing a least-authority alternative to conventional file and network APIs.readable
and editable
file interfaces that map closely to our approach:type readable = {
isDir : unit -> bool;
exists : unit -> bool;
subRdFiles : unit -> readable list;
subRdFile : string -> readable;
inChannel : unit -> in_channel;
getBytes : unit -> string;
fullPath : unit -> string;
}
type editable = {
ro : readable;
subEdFiles : unit -> editable list;
subEdFile : string -> editable;
outChannel : unit -> out_channel;
setBytes : string -> unit;
mkDir : unit -> unit;
createNewFile : unit -> unit;
delete : unit -> unit;
}
java.io.File
.These systems share the goal of enabling secure cooperation through modular, delegatable authority. @agoric/pola-io
brings these patterns to JavaScript I/O.
Just like the PictureBook describes, this package is about delegating only what is necessary, and composing secure patterns like revocation, logging, and least authority by default. Think:
Applying these techniques uniformly leads to systems where cooperation is safer, authority is easier to reason about, and trust boundaries are clear.
Please do! See CONTRIBUTING.