@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
112 lines • 6.36 kB
TypeScript
import type { RouteContext } from './types.ts';
import type { Action, CommandContext, CommandResultContext, ExecuteResultContext, NetworkContext, NetworkResultContext, VfsContext, VfsResultContext, SessionContext, SessionResultContext, WorkspaceContext } from './types.ts';
/**
* One concern's answers to the workspace lifecycle.
*
* Implementations define only the methods they care about; a method
* returns an Action to state an opinion, an array of them to state
* several (each read as if its own policy had said it, as a profile's
* programs answer), or null to stay silent (directly or as a promise;
* the seam awaits either), and a method that throws fails closed (the
* command is refused, naming the policy).
* Undefined methods are detected at the seam and never called.
*
* The methods come in pairs, one per surface: the line (`preExecute` /
* `postExecute`), each command or CLI (`preCommand` / `postCommand`),
* each `ws.vfs` / `session.vfs` call (`preVfs` / `postVfs`) and each
* session write (`preSession` / `postSession`). Every method may answer
* Deny or Ask; a Limit only at `postExecute`, where a line's output comes
* back to cap, a Route only at `preExecute`. One more, `preWorkspace`,
* answers on a server before a workspace is built, with a Deny only. A
* post method sees what
* its pre method saw, plus what came back, and never undoes a side effect:
* it holds back what came back. Hides, mount modes and path rules are
* not methods: they apply to every caller at the dispatcher. Every method's
* context also carries the session (`session`) and its files (`vfs`), both
* read only: a method reads, and a write it makes is refused. Mirrors the
* Python Policy.
*/
export interface Policy {
/**
* Place, hold or refuse one typed line before any of it runs. Fires
* once per line, after the profile's rules clear it (a line they
* refuse is never placed) and before it runs; a nested line keeps the
* placement of the line that ran it. A Route names the runtime that
* serves the line, a Deny refuses it whole (exit 126,
* `<command>: Permission denied`) and an Ask holds it until the host
* approves. The workspace's `routePolicy` answers here as a built-in,
* ahead of the policies registered in code.
*/
preExecute?(ctx: RouteContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Admit, hold or refuse one command or CLI, once, as it runs. A Deny
* refuses it (`<command>: Permission denied`, exit 126, or the
* operand's own error for an operand refusal); an Ask holds it until
* the host approves. Its file I/O also passes the dispatcher's
* `preVfs` and `postVfs` gates.
*/
preCommand?(ctx: CommandContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Judge one command or CLI once it ran and its output drained. A Deny,
* or an Ask the host has not approved, sets its exit code to 126 and
* records the refusal, so `&&` and `pipefail` stop there; output
* already sent stays sent.
*/
postCommand?(ctx: CommandResultContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Admit, hold or refuse one `ws.vfs` / `session.vfs` call. Fires at the
* dispatcher before any backend or cache I/O, for the host's and the
* agent's file calls, including commands, runtimes and FUSE. A Deny
* is EACCES; an Ask holds a standalone call until the host approves
* and refuses inside a running command.
*/
preVfs?(ctx: VfsContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Judge one completed `ws.vfs` / `session.vfs` call. A Deny, or an Ask
* the host has not approved, drops the result with EACCES (the call
* itself is not undone). Nothing cuts a result: a kernel or protocol
* mount reads in ranges and must get each whole.
*/
postVfs?(ctx: VfsResultContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Admit or refuse one request a command sends, before any connection
* opens, for `curl`, `wget` and `git` over https. A Deny refuses it as a
* closed port would (`curl` exits 7); an Ask refuses it too, since the
* line was admitted without it.
*/
preNetwork?(ctx: NetworkContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Judge one finished request, once the transfer ends however it ends, so
* a method can count what is in flight. A Deny fails the command as a
* broken transfer; what it already wrote stays.
*/
postNetwork?(ctx: NetworkResultContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Admit, hold or refuse one session write (set, unset, mark) on the
* session plane, before it lands. Not path-scoped on purpose: the
* context carries a key, never a pseudo-path.
*/
preSession?(ctx: SessionContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Judge one session write once it landed. A Deny, or an Ask the host
* has not approved, puts the old value back and refuses the write.
*/
postSession?(ctx: SessionResultContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Judge one finished line's output: what `preExecute` saw, plus the exit
* code, the output and each command's result. A Deny, or an Ask the host
* has not approved, drops the output (exit 126, a refusal record); a
* Limit merges with every other opining policy's (tightest per field)
* and caps it at the workspace boundary.
*/
postExecute?(ctx: ExecuteResultContext): Action | Action[] | null | Promise<Action | Action[] | null>;
/**
* Refuse a workspace a server is about to build: on a create, clone or
* load, before any mount is built or any secret the config names is
* read, for the policies the server was started with; a workspace's
* own policies cannot answer, as it does not exist yet. A Deny refuses
* the request with 403 and its reason; nothing else may be answered.
*/
preWorkspace?(ctx: WorkspaceContext): Action | Action[] | null | Promise<Action | Action[] | null>;
}
//# sourceMappingURL=base.d.ts.map