Permissions
Devlish programs can declare their required permissions, resource boundaries, and allowed callers in a manifest header. When present, the VM enforces these declarations at runtime.
Manifest Format
Section titled “Manifest Format”The manifest appears at the top of a .dvl file, before the program body:
Permissions: Read files from "/inbox/" Write files to "/receipts/" HTTP requests to "api.example.com" Filesystem operations on "/data/" Call Gmail service
Boundaries: No writes outside "/Users/admin/Dropbox/Financials/"
Callers: Any MCP client
# Program body starts hereRead JSON from "/inbox/invoice.json" as invoicePermission Types
Section titled “Permission Types”| Permission | Syntax | Effect |
|---|---|---|
| Read files | Read files or Read files from "<path>" |
Allow file reads (optionally scoped to path prefix) |
| Write files | Write files or Write files to "<path>" |
Allow file writes (optionally scoped) |
| HTTP requests | HTTP requests or HTTP requests to "<domain>" |
Allow HTTP calls (optionally scoped to domain) |
| Filesystem | Filesystem operations or Filesystem operations on "<path>" |
Allow copy, move, delete, mkdir, list, glob |
| Service calls | Call <ServiceName> service |
Allow calls to a named external service |
Scoped vs Unscoped
Section titled “Scoped vs Unscoped”Scoped permissions (with from, to, or on) restrict effects to paths starting with the given prefix:
Permissions: Read files from "/data/projects/" Write files to "/output/"Unscoped permissions allow all paths for that effect type:
Permissions: Read files Write filesRuntime Enforcement
Section titled “Runtime Enforcement”When a manifest with permissions is present, the VM checks every effect against the declared permissions. An undeclared effect produces a “Permission denied” error:
Permissions: Read files from "/inbox/"
# This succeeds:Read JSON from "/inbox/data.json" as data
# This fails at runtime with "Permission denied":Read JSON from "/secrets/keys.json" as keysPrograms without any manifest remain unrestricted for backward compatibility.
Boundaries
Section titled “Boundaries”Boundaries add hard constraints regardless of other permissions:
Boundaries: No writes outside "/Users/admin/Dropbox/Financials/"Callers
Section titled “Callers”Caller declarations are metadata for documentation and tooling. They compile into the bytecode package so clients can inspect them before invocation:
Callers: Any MCP clientCompiled Representation
Section titled “Compiled Representation”The manifest compiles into the .dvlc.json bytecode package:
{ "manifest": { "permissions": [ {"kind": "read_file", "scope": "/inbox/"}, {"kind": "write_file", "scope": "/receipts/"}, {"kind": "http_request", "scope": "api.example.com"} ], "boundaries": ["No writes outside \"/Users/admin/Dropbox/\""], "callers": ["Any MCP client"] }}This allows MCP clients, deployment systems, and code review tools to understand what a program does without executing it.
Security Model
Section titled “Security Model”The permission system follows a “default open, opt-in restrict” model:
- No manifest: program can do anything the host allows
- With manifest: only declared effects are permitted
- The
devlish-runtimenpm package rejects tools that declare HTTP or filesystem permissions at load time (sandboxed WASM execution)