# `ExSandbox.Egress.Verification`
[🔗](https://github.com/FoundryStack/ex_sandbox/blob/v1.2.0/lib/ex_sandbox/egress/verification.ex#L1)

Whether a running sandbox is *policed* rather than merely *isolated*
(005 T060a3/T060a5, `contracts/egress.md` §Capability probing).

## The coincidence this replaces

`Hardening.Linux.sandbox_netns_separated?/1` compares namespace inodes. Under
`--unshare-net` that was enough, because an empty namespace has no route and
so isolation and policy coincided. `ExSandbox.Egress.LaunchPlan` installs a
working default route, which ends the coincidence: separation is now true for
a namespace that reaches the pool *and* for one that reaches nothing.

⚠️ Separation alone must therefore stop counting as success. A sandbox in its
own namespace with **no registered policy** reaches nothing — which passes
every denial check in the conformance suite, because a boundary permitting
nothing is indistinguishable from a correct one under a suite that only tests
denial (`contracts/egress.md`, "What is wrong today").

## Why this takes a map rather than reading `/proc` itself

The two facts it joins come from different places — the kernel for the
namespace, the `Registry` for the policy — and neither is reachable from a
macOS host. Taking them as data makes the *join* testable everywhere, which
matters because the join is the part that was missing, not either fact.

# `observation`

```elixir
@type observation() :: %{
  netns_separated: boolean() | :unknown,
  source_key: ExSandbox.Egress.Policy.source_key(),
  registered_allowlist: [ExSandbox.Egress.Policy.destination()]
}
```

# `refusal`

```elixir
@type refusal() :: :no_policy | :not_separated | :unverifiable
```

Why a sandbox is not confirmed policed.

# `policed?`

```elixir
@spec policed?(observation()) :: :ok | {:error, refusal()}
```

`:ok` only when the sandbox is in its own namespace **and** a policy is
registered for its /30.

Every other outcome is an error naming which half is missing. There is no
outcome meaning "probably fine".

---

*Consult [api-reference.md](api-reference.md) for complete listing*
