sharness.ai / the landscape / enforceability · this page as markdown

Enforceability: which rows of a policy can run where

Status: a map, as of 25 Oct 2026, from each target's documentation as read for the market analysis and from the CLI's own code; no translation has been run against its target in this project. Each cell answers the three questions of the landscape: can the row be expressed, can the target enforce it, and as what kind of barrier. The command sharness-ai policy translate FILE --to TARGET writes the translation and prints the gap for the first four columns (E10).

1. The matrix

Barrier kinds are ABP's: B a Boundary (enforced above the subject, by the kernel or a separate process); S a Setting (the subject's own process reads and could change it); E an Expectation (prose, or a check the subject performs on itself); – nothing.

Policy row (v0 and the designed schema)SHarness (run today)bubblewrapDocker (run)Claude Code sandboxKubernetes Pod + NetworkPolicymicroVM providers (E2B, Fly, Docker Sandboxes)ToolHive (MCP servers)OpenShell (NemoClaw)
files.read as an allowlistB LandlockB ro-binds (the rest absent)B the image, read-only– reads most of the machine; denyRead is a deny listB the image; host paths as volumesB the guest's own diskB container with profile pathsB "filesystem controls" (not detailed)
files.writeB LandlockB bindsB volumesB allowWriteB volumesBBB
files.exec allowlistB Landlock– read implies exec–––––not stated
network: noneB empty namespace (+ Landlock)B --unshare-netB --network noneB proxy with an empty allowlist (UDP cannot leave)B NetworkPolicy egress []BB --isolate-networkB "blocks unapproved destinations"
network.connect_tcp_portsB Landlock ports–– (needs iptables)– domains, not portsB NetworkPolicy portsvariespartial (hosts and ports in the profile)not stated
host namesdesigned: sharness.net as the TLS client––S/B hostname proxy (not TLS-terminating; managed settings make it B for the user)– without a meshB at the provider's egress (Cloudflare, Docker Sandboxes)B egress proxyB operator-approved destinations
process.max_memory_mbB rlimit + cgroup–B --memory–B resources.limitsB the VM sizeB container limitsnot stated
process.max_pidsB rlimit + cgroup–B --pids-limit–– per podBBnot stated
no_new_privs, no capabilitiesBBB --cap-drop ALL, no-new-privilegesB (bubblewrap underneath)B securityContextBBB
a separate uid per componentdesigned (launcher)B user namespaceB --user– one uidB runAsUserBB per containernot stated
seccomp allowlist from the policydesignedB (--seccomp takes a filter)B --security-opt seccomp=– (optional Unix-socket filter only)S RuntimeDefault, or a Localhost profile (B)provider'sB container runtime default"process controls"
IPC edges (who may talk to whom)designed: mutual TLS, both sides check–– (networks, not roles)–partial: NetworkPolicy between pods–––
the model (sharness.llm: pinned tools, secret filter)designed––S allowedMcpServers, permissions (the agent's own settings)–––B managed inference through inference.local
secrets never in the agent's processdesigned (sharness.kms)––S credential masks at the proxy (the clear key is in the proxy)– (a Secret is mounted into the pod)B credentials injected outside the VM (Docker Sandboxes, Cloudflare)B secrets into the container process onlyB "credentials remain outside the sandbox"
the policy hash supplied from outsideB --expect-hash (for a child)––– (settings are the subject's own; managed settings are B for the user)– (an admission controller could)–––
who enforcesthe process itself today (S for itself); the launcher, designedthe callerthe daemonthe agent's process; managed settingsthe kubelet and the CNIthe providerthe gatewaythe OpenShell host

Legend for "not stated": the product's documentation read for the market analysis does not say; "varies": differs by provider.

2. Reading the matrix

3. The command

$ sharness-ai policy translate experiments/policies/allow-https-example.json --to bwrap -- python3 -c "print(1)"
bwrap --unshare-all --die-with-parent --new-session --cap-drop ALL --share-net --ro-bind /bin /bin --ro-bind /etc /etc \
  --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /usr /usr -- python3 -c 'print(1)'

# bwrap: not enforced from policy allow-https-example (sha256:2944751573bb…):
#   - no_new_privs: bwrap sets it (PR_SET_NO_NEW_PRIVS) for the sandboxed process
#   - network.connect_tcp_ports [443]: not enforced; bwrap shares or unshares the whole network, it has no port allowlist
#   - files.exec: not distinct from files.read; a read-only bind is also executable in bwrap (use noexec mounts or Landlock inside)

The same for --to docker, --to claude-code (a settings.json fragment) and --to kubernetes (a Pod and a NetworkPolicy). Every output ends with the list of what the target does not enforce, which is the matrix row by row, made executable. --to landlock prints what run itself does, for completeness.

4. What the matrix does not say

Sources: the market analysis and each product's documentation it cites; Policies §5, the enforcement map; sharness_ai/translate.py on the CLI's dev branch; riskmandate.ai/abp for the barrier kinds.