UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

112 lines • 6.36 kB
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