sharness.ai / the design / what a process can do · this page as markdown

What a process can do: the whole surface

Status: design, with the measured rows dated. The question behind this page is Dinis Cruz's: if we limit everything else, what else can a process do? The answer is a list, and it is short enough to write down. For each kind of thing a process can do, this page says what SHarness bounds it with, whether that bound was measured (as of 24 Oct 2026, in one Claude agent workspace), and what the bound does not cover.

1. A process touches the world through the kernel, and only through the kernel

Everything a user-space process does outside its own memory is a system call. Linux has about 460 of them on x86-64; sgit --version uses 38 distinct ones (measured, Evidence §5), a bare Python start 31. They group into a dozen kinds of interface. A process that is bounded on every kind is a process whose operating system is its policy: what the policy lists exists, and nothing else does. That is the idea the design calls a Process Behaviour Policy, read from the other side.

The whole surface of a process: twelve kinds of interface arranged around one process, each with what bounds it in SHarness.
The whole surface. Green: bounded in the kernel. Purple: bounded by a separate component, because the kernel cannot see the thing being bounded (which host a TLS connection names, what a model is asked, what a secret is).

2. The surface, one row per interface

InterfaceWhat a process can do through itBounded by (kernel)The allowed part goes throughMeasuredNot covered by the bound
files: read, write, execute, create, delete, renameread any file its uid can; write; exec a binary; make device nodes, sockets, symlinksLandlock path rules per process (ABI 1+); exec allowlist; the workspace with no execute right; a mount namespace with read-only bindssharness.fs, the only writer of protected folders, with content rules (no clear keys)read and write denial ✔ (E03, E04); exec allowlist and read-only binds: not yetthe content of what it may read: prompt injection travels inside allowed files
network: connect, listen, send, receive, resolve namesreach any host; listen on any port; UDP, raw socketsan empty network namespace (nothing at all), or Landlock TCP port rules (ABI 4+); iptables per uidsharness.net, the only client, and the TLS client, so it sees and verifies the host name; endpoint and vault-id allowlistsnamespace ✔, port rules ✔, per-uid rule ✔UDP and ICMP under Landlock alone (the namespace covers them); what is sent on an allowed connection
processes: fork, exec, clonestart anything on the system; start itself againRLIMIT_NPROC=0 or a pids cgroup; seccomp denying execve after start; Landlock execute rightssharness.bash: a server outside the domain runs each command in a fresh sandboxno-fork ✔; the server design not yet run (E06)a binary the policy lets it run (which is why node for the orchestrator is pinned by hash)
signals and IPC: kill, ptrace, pipes, Unix sockets, shared memory, abstract socketssignal or trace another process; reach a socket by nameLandlock scoping of signals and abstract sockets (ABI 6+); a pid namespace (cannot even see the others); ptrace denied by seccompthe mutual TLS edges: the only IPC that exists is the edge list, with roles in certificates and both sides checkingedges ✔ (exactly per the matrix); scoping and seccomp not yeta message on an allowed edge: its schema bounds its shape, not its intent
memoryuse as much as it likes; keep secrets in ordinary pages root can reada memory cgroup; PR_SET_DUMPABLE=0, mlockall, RLIMIT_CORE=0secrets in memfd_secret pages, scrubbed after copyingmemfd_secret unreadable even by root ✔; dumpable stops non-root only ✔root reading ordinary memory (out of scope); OpenSSL's own copies during an operation
time and limitsrun for ever; spin the CPUmax_runtime_s; a cpu cgroup; the freezerthe launcher freezes sharness.kms between callsfreeze 0.28 ms / thaw 0.13 ms ✔timing as a covert channel
devices and mountsopen device nodes; mount; ioctlno device nodes in the namespace; a mount namespace; Landlock IOCTL_DEV (ABI 5+); mount denied by seccompnothing: components need no devicesnamespaces ✔ (3.7 ms); read-only binds not yet
identity and privilegechange uid; use capabilities; gain privilege through setuid binariesone ephemeral uid per component, made for the session; bounding set empty; no_new_privsthe launcher makes the uids and deletes them✔ (49 ms per user, with a firewall rule and teardown)root undoing it, when the agent is root and runs the launcher itself
kernel serviceskeyctl, bpf, unshare, mount, ptrace, io_uring, userfaultfd and the rest of the long taila seccomp-BPF allowlist of the 30 to 40 syscalls a component usesnothingavailable; no filter tested yeta bug in an allowed syscall (the kernel is trusted)
environment and argumentsread secrets from argv and environ; the transcript sees boththe launcher sets them; nothing secret is ever in eitherSHARNESS_AI_POLICY_HASH and the policy id, so a process can say what it runs underE03 sets them ✔
the model (an agent's interface)ask the model anything, with any tools, with any secret in the contextnothing in the kernel: the model API is an HTTPS host like any othersharness.llm: model allowlist, pinned tool list, token budget, a secret filter on every tool result and user message, the real key added lastdesigned (E07)the model being talked into a bad tool call: enforced where the tool executes, not here
secretshold a key, print it, write it, pass it onnothing in the kernel; memfd_secret only hides the pagesharness.kms: opens sealed things and returns derived keys sealed to a one-time key; never a clear keythe holding ✔ (§ memory); the protocol designed (E08)expiry is KMS policy, not cryptography; a session identity dies with its session

Rows marked ✔ were measured on 24 Oct 2026, in one Claude agent workspace, with method on Evidence; the rest is designed or planned. The policy fields behind each row are in the schema on Policies §4 and the enforcement map on Policies §5.

3. What is left: a virtual operating system for one process

Read the table from the right. Take away every interface that is bounded to nothing, and what remains for a component is:

That is a complete description of the process's world. It is small enough to hash, to read in one sitting, to learn from a trace, and to ship with the code it binds. Nothing in it is new: it is what a kernel already offers, used all at once for one process, with the parts the kernel cannot see (host names, model requests, secrets) each given to one small process that can. The design calls the whole thing a harness; it could as well be called a virtual operating system whose system call table is the policy.

4. What this does not bound

5. Where each bound is, today

In the CLI today (v0 policy)Designed, not built
files (Landlock read, write, exec); network (none, or TCP ports); no_new_privs; the environment carrying the hashper-component uids, seccomp allowlists, cgroups, scoping, read-only binds, the launcher, sharness.fs, .net, .bash, .llm, .kms

The v0 policy covers the two interfaces that leak most (files and network) for one process; each further row is one experiment on the ladder.

Sources: Policies §4 and §5; Components; Evidence §3 to §6 and §9; the Landlock documentation at docs.kernel.org; sgit --version under strace -c on 24 Oct 2026 (36 distinct syscalls by that method, 38 by the design's).