import type { AuthorizationGateConfig } from '../types/authorization/index.js'; import type { SandboxIsolationControl, SandboxIsolationReport } from '../types/sandbox/index.js'; /** * A named permission stance: what the gate allows, what the sandbox must * actually enforce for that to be safe, and who answers the rest. * * The three were configured independently and had to agree by hand. * `defaultSandboxedGateConfig` auto-approves in-sandbox file mutation, and * its own docstring says why: "the FS boundary is enforced by the sandbox * layer, not by per-call review". That is a claim about a DIFFERENT * subsystem — one nothing checked. Hand that config a `basic` tier, where * the spawned process can read and write the whole host filesystem, and the * gate keeps auto-approving writes on the grounds of a boundary that is not * there. * * So a preset states its requirement and {@link resolvePermissionPreset} * refuses when the host cannot meet it. Refusing is the point: a preset * that silently fell back to asking about everything would be safe and * unusable, and one that silently kept auto-approving would be neither. */ export interface PermissionPreset { /** Stable, and written into the turn's log. */ readonly name: string; /** One sentence an operator reads when choosing between them. */ readonly description: string; readonly gate: AuthorizationGateConfig; /** * The controls the sandbox must actually enforce for `gate` to mean what * it says. * * Controls, not a tier name. `SandboxEnvironment` names an * implementation — one tier denies the network outright while another * leaves the host filesystem visible — and a preset depends on the * property, not on which implementation happens to supply it. */ readonly requiresIsolation: readonly SandboxIsolationControl[]; /** * The approval policy name this stance expects to be running under. * * Advisory rather than enforced: this package cannot install a handler, * and a preset that pretended to would be claiming an authority it does * not have. It is here so a host can compare it against the turn's actual * policy and so the pairing is written down in one place instead of * living in whoever wired it. */ readonly expectsApprovalPolicy: string; } /** A preset whose isolation requirement the host cannot meet. */ export declare class UnsupportedPermissionPresetError extends Error { readonly details: { preset: string; required: readonly SandboxIsolationControl[]; missing: readonly SandboxIsolationControl[]; }; constructor(details: { preset: string; required: readonly SandboxIsolationControl[]; missing: readonly SandboxIsolationControl[]; }); } /** * Ask a human about everything, and rely on nothing. * * The only preset with no isolation requirement, because it makes no * assumption a sandbox could fail to back: every call goes to review. * Correct on a bare host, and the one to reach for when the sandbox tier * is unknown. */ export declare const SUPERVISED_PRESET: PermissionPreset; /** * Trust the sandbox for the filesystem; ask about shell and network. * * `filesystem` only, and the omissions are deliberate. This preset does not * auto-approve shell or network calls, so it does not depend on those * controls being enforced — requiring them would refuse hosts that could * safely run this. */ export declare const SANDBOXED_PRESET: PermissionPreset; /** * Trust the sandbox for shell too. * * Requires `process` as well: a shell that auto-approves inside a tier * which cannot stop it seeing or signalling host processes is a shell with * the run of the machine, and the gate would be approving on the strength * of a boundary that does not exist. */ export declare const SANDBOXED_SHELL_PRESET: PermissionPreset; /** * Nobody is watching, so the sandbox has to be. * * All three controls, because with an auto-approving policy the sandbox is * the ONLY boundary left. This is the preset an unattended turn wants, and * the one whose requirement must not be waived: the whole reason it can * approve everything is that the host said nothing can escape. */ export declare const UNATTENDED_PRESET: PermissionPreset; export declare const PERMISSION_PRESETS: Readonly>; /** The preset by name, or `undefined` — the reverse lookup a host needs. */ export declare function permissionPreset(name: string): PermissionPreset | undefined; /** * The gate config for a preset, or a refusal naming what is missing. * * The check is the reason this function exists rather than a property * lookup. A host reaching for `unattended` on a `basic` tier is asking for * a turn that approves everything with nothing enforcing the boundary it is * approving on the strength of; the answer is no, with the missing controls * named so the host can fix the sandbox rather than guess. */ export declare function resolvePermissionPreset(preset: PermissionPreset, isolation: SandboxIsolationReport): AuthorizationGateConfig; /** * Every preset this host can actually honour, strongest first. * * For an operator picking one, and for a host that wants a default it can * defend. Ordered by how much they rely on the sandbox rather than * alphabetically, so the first entry is always the loosest stance this host * can back up and the last is always `supervised`, which needs nothing. */ export declare function availablePermissionPresets(isolation: SandboxIsolationReport): readonly PermissionPreset[]; //# sourceMappingURL=permission-presets.d.ts.map