<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Getting Started on Scrutineer</title>
    <link>http://scrutineer.sh/docs/getting-started/</link>
    <description>Recent content in Getting Started on Scrutineer</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 12 Jul 2026 00:00:00 -0700</lastBuildDate>
    <atom:link href="http://scrutineer.sh/docs/getting-started/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Quickstart</title>
      <link>http://scrutineer.sh/docs/getting-started/quickstart/</link>
      <pubDate>Tue, 07 Jul 2026 00:00:00 -0700</pubDate>
      <guid>http://scrutineer.sh/docs/getting-started/quickstart/</guid>
      <description>One command to a running, lock-verified Scrutineer on a local kind cluster — about five minutes.</description>
      <content:encoded><![CDATA[<p>One command, a local <a href="https://kind.sigs.k8s.io/">kind</a> cluster, about five minutes —
and the enforcement guarantee is <em>proved</em>, not assumed, before it reports success.
(Prefer to see every step on your own cluster?
<a href="/docs/getting-started/install/">Install on your cluster</a>.)</p>
<details class="docs-details">
  <summary>0 · Prerequisites</summary>
  <div class="docs-details-body">
    <ul>
<li><strong>Docker</strong>, <strong>kind</strong>, <strong>kubectl</strong>, and <strong>Go ≥ 1.21</strong> on your PATH (kind v0.31–v0.32
tested). Any modern Go works — the build pins its own exact toolchain.
Missing something? <code>make quickstart</code> names it and shows the install command.</li>
<li>Internet egress from the cluster — the sample agents fetch <code>example.com</code>.</li>
<li>~5 minutes on a first run — the images are always built from your checkout, never
pulled, so what runs is exactly what you cloned. Repeats are faster.</li>
</ul>

  </div>
</details>

<details class="docs-details">
  <summary>1 · Run it</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git clone https://github.com/grantbarry29/scrutineer.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> scrutineer
</span></span><span class="line"><span class="cl">make quickstart
</span></span></code></pre></div><p>Creates a <code>scrutineer-quickstart</code> kind cluster, installs Scrutineer, then runs a
canary probe to prove the CNI actually enforces NetworkPolicy. It ends with the
verdict:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">&gt;&gt; routing-lock enforcement VERIFIED on this cluster (enforced sessions will run).
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>2 · If it says REFUSED</summary>
  <div class="docs-details-body">
    <p>Your CNI doesn&rsquo;t enforce NetworkPolicy, so Scrutineer refuses to claim enforcement
rather than pretend. Retry on Calico:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">make quickstart-down
</span></span><span class="line"><span class="cl">make quickstart <span class="nv">QUICKSTART_CNI</span><span class="o">=</span>calico
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>3 · Try a sample session</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl apply -f config/samples/scrutineer_v1alpha1_agentsession.yaml
</span></span><span class="line"><span class="cl">kubectl get agentsessions -w
</span></span><span class="line"><span class="cl">kubectl get agentsession github-readme-update -o yaml   <span class="c1"># the run&#39;s record, evidence included</span>
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>4 · Tear down</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">make quickstart-down
</span></span></code></pre></div>
  </div>
</details>

<p>Next: the <a href="/docs/getting-started/demo/">demo</a> — a live denial, a dead bypass attempt,
and evidence the agent couldn&rsquo;t forge, in one run.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Demo: untamperable egress governance</title>
      <link>http://scrutineer.sh/docs/getting-started/demo/</link>
      <pubDate>Tue, 07 Jul 2026 00:00:00 -0700</pubDate>
      <guid>http://scrutineer.sh/docs/getting-started/demo/</guid>
      <description>Two sessions, same bring-your-own agent: a live denial, a bypass attempt killed by the routing lock, and evidence the agent couldn&amp;rsquo;t forge.</description>
      <content:encoded><![CDATA[<p>One run, two sessions, same plain-busybox agent: one <code>enforced</code>, one <code>audit-only</code>.
You&rsquo;ll see a denied request rejected live, a bypass attempt die in the kernel, and all
of it recorded as evidence the agent couldn&rsquo;t forge.</p>
<details class="docs-details">
  <summary>0 · Prerequisites</summary>
  <div class="docs-details-body">
    <p>A <a href="/docs/getting-started/quickstart/">quickstart</a> cluster that ended <code>VERIFIED</code>, with
internet egress (the demo fetches <code>example.com</code>).</p>

  </div>
</details>

<details class="docs-details">
  <summary>1 · Run it</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">make demo
</span></span></code></pre></div><p>Applies one hardened <code>RuntimeProfile</code>, two <code>AgentPolicy</code> objects differing <strong>only in
<code>mode</code></strong>, and two sessions running the same busybox agent — nothing in the image
cooperates with enforcement. Each agent probes three paths and prints what it
experienced (~2 minutes):</p>
<table>
	<thead>
			<tr>
					<th>probe</th>
					<th><code>demo-enforced</code></th>
					<th><code>demo-audit</code></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>example.com</code> via the proxy (allowlisted)</td>
					<td><code>SUCCEEDED</code></td>
					<td><code>SUCCEEDED</code></td>
			</tr>
			<tr>
					<td><code>example.net</code> via the proxy (not allowlisted)</td>
					<td><code>BLOCKED</code></td>
					<td><code>SUCCEEDED</code>, recorded as <code>dry-run</code></td>
			</tr>
			<tr>
					<td>direct DNS, skipping the proxy (bypass attempt)</td>
					<td><code>BLOCKED</code></td>
					<td><code>BLOCKED</code></td>
			</tr>
	</tbody>
</table>
<p>Notice: the proxy env is a convenience, not the control — the default-deny
NetworkPolicy is why the bypass dies. And it dies in <strong>both</strong> modes: <code>audit-only</code>
relaxes blocking, never the routing lock, or the observations couldn&rsquo;t be trusted.</p>

  </div>
</details>

<details class="docs-details">
  <summary>2 · Read the evidence</summary>
  <div class="docs-details-body">
    <p><code>make demo</code> ends by printing <code>status.policyDecisions</code> for both sessions.</p>
<ul>
<li><strong>action</strong> — <code>deny</code> (enforced) vs <code>dry-run</code> (audit) for <code>example.net</code>. Mode changed
what <em>happened</em>, never what was <em>seen</em>.</li>
<li><strong>assurance</strong> — every entry is <code>observed</code>: reported by the proxy pod under its own
identity. The agent has no path to inject or launder evidence.
(<a href="/docs/concepts/core-concepts/#evidence-assurance">Why.</a>)</li>
<li><strong>what&rsquo;s absent</strong> — the bypass attempt left no entry. The CNI drops it silently;
recording attempts unforgeably is a tracked roadmap item, stated rather than hidden.</li>
</ul>
<p>Dig further:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl get agentsession demo-enforced -o yaml
</span></span><span class="line"><span class="cl">kubectl get events --field-selector involvedObject.name<span class="o">=</span>demo-enforced
</span></span><span class="line"><span class="cl">kubectl get pods -l scrutineer.sh/session
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>3 · Honest boundaries</summary>
  <div class="docs-details-body">
    <ul>
<li>External TLS is tunneled: filtering is by domain, not request bodies.</li>
<li>Tool and file governance have no enforcement backend yet — removed rather than
shipped as advisory; they return as out-of-pod chokepoints.</li>
<li>The guarantee assumes an enforcing CNI (proved by the gate) and an uncompromised
node — spelled out in the
<a href="https://github.com/grantbarry29/scrutineer/tree/main/docs/design">design docs</a>.</li>
</ul>

  </div>
</details>

<details class="docs-details">
  <summary>4 · Clean up</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">make demo-down        <span class="c1"># remove the demo sessions/policies/profile</span>
</span></span><span class="line"><span class="cl">make quickstart-down  <span class="c1"># delete the kind cluster entirely</span>
</span></span></code></pre></div>
  </div>
</details>

<p>Next: <a href="/docs/getting-started/install/">install on your cluster</a> — the same story,
every command visible, on your own cluster.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Install on your cluster, step by step</title>
      <link>http://scrutineer.sh/docs/getting-started/install/</link>
      <pubDate>Sun, 12 Jul 2026 00:00:00 -0700</pubDate>
      <guid>http://scrutineer.sh/docs/getting-started/install/</guid>
      <description>Every command visible, on your existing cluster: install, deny one domain, run an agent, read the proof.</description>
      <content:encoded><![CDATA[<p>The <a href="/docs/getting-started/quickstart/">quickstart</a> is one command that hides the
steps. Here they all are, on your own cluster. You&rsquo;ll install Scrutineer, deny one
domain, run an agent that tries it, and read proof of the block.</p>
<details class="docs-details">
  <summary>0 · Prerequisites</summary>
  <div class="docs-details-body">
    <ul>
<li>A cluster and <code>kubectl</code>.</li>
<li>A CNI that enforces egress NetworkPolicy (Calico, Cilium, and kind&rsquo;s default all
do). Unsure? Scrutineer checks for you — step 2.</li>
<li>Nodes that can pull from <code>ghcr.io</code> and Docker Hub.</li>
<li>Internet egress from pods — the audit-mode run in step 7 really fetches
<code>example.com</code>.</li>
</ul>
<p>No cert-manager, no webhooks — the install is just CRDs, RBAC, and one controller.</p>

  </div>
</details>

<details class="docs-details">
  <summary>1 · Install the CRDs and controller</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git clone --depth <span class="m">1</span> --branch v0.2.0 https://github.com/grantbarry29/scrutineer.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> scrutineer
</span></span><span class="line"><span class="cl">kubectl apply -k config/crd
</span></span><span class="line"><span class="cl">kubectl apply -k config/default
</span></span><span class="line"><span class="cl">kubectl -n scrutineer-system rollout status deployment/scrutineer-controller-manager
</span></span></code></pre></div><p>Want to inspect before applying? <code>kubectl kustomize config/default | less</code>.</p>

  </div>
</details>

<details class="docs-details">
  <summary>2 · Check the enforcement verdict</summary>
  <div class="docs-details-body">
    <p>Scrutineer tests your CNI with canary pods instead of trusting it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl -n scrutineer-system logs deployment/scrutineer-controller-manager <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="p">|</span> grep <span class="s1">&#39;lock probe verdict&#39;</span> <span class="p">|</span> tail -1
</span></span></code></pre></div><p><code>Verified</code> — enforcement is real. <code>Refused</code> — your CNI ignores NetworkPolicy, so
Scrutineer will only run <code>audit-only</code> sessions rather than fake enforcement.</p>

  </div>
</details>

<details class="docs-details">
  <summary>3 · Create a runtime profile</summary>
  <div class="docs-details-body">
    <p>How governed agents run. The <code>envoy</code> entry gives each session its own proxy pod and
locks the agent&rsquo;s network to it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># runtimeprofile.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">scrutineer.sh/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">RuntimeProfile</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">enforced-egress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">container</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">runAsNonRoot</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">runAsUser</span><span class="p">:</span><span class="w"> </span><span class="m">65532</span><span class="w">        </span><span class="c"># busybox runs as root by default; remap it</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">runAsGroup</span><span class="p">:</span><span class="w"> </span><span class="m">65532</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">readOnlyRootFilesystem</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">allowPrivilegeEscalation</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">capabilities</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">drop</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;ALL&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pod</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">seccompProfile</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">RuntimeDefault</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">enforcement</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">envoy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">envoy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl apply -f runtimeprofile.yaml
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>4 · Write a rule</summary>
  <div class="docs-details-body">
    <p>Deny one domain, enforced:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># policy.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">scrutineer.sh/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">AgentPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">deny-example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="l">enforced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">deniedDomains</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">example.com</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl apply -f policy.yaml
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>5 · Run a governed session</summary>
  <div class="docs-details-body">
    <p>The agent is plain busybox — it doesn&rsquo;t know Scrutineer exists. It tries the denied
domain:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># session.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">scrutineer.sh/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">AgentSession</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">first-session</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">task</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="l">Try one denied egress and exit</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">prompt</span><span class="p">:</span><span class="w"> </span><span class="l">noop</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">model</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">provider</span><span class="p">:</span><span class="w"> </span><span class="l">openai</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">gpt-4.1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">runtime</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">orchestrator</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes-job</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">busybox:latest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">sh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- -<span class="l">c</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">      wget -q -O /dev/null http://example.com/ \
</span></span></span><span class="line"><span class="cl"><span class="sd">        &amp;&amp; echo &#34;egress succeeded&#34; \
</span></span></span><span class="line"><span class="cl"><span class="sd">        || echo &#34;egress blocked&#34;
</span></span></span><span class="line"><span class="cl"><span class="sd">      exit 0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">runtimeProfileRef</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">enforced-egress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyRefs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">AgentPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">deny-example</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl apply -f session.yaml
</span></span><span class="line"><span class="cl">kubectl get agentsessions -w        <span class="c1"># Pending → Running → Succeeded</span>
</span></span></code></pre></div><p>While it runs, <code>kubectl get pods,networkpolicies</code> shows the agent pod, the
<code>first-session-egress</code> proxy pod, and two NetworkPolicies: the routing lock on the
agent, a backstop on the proxy.</p>

  </div>
</details>

<details class="docs-details">
  <summary>6 · Read the evidence</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl get agentsession first-session -o <span class="nv">jsonpath</span><span class="o">=</span><span class="s1">&#39;{.status.policyDecisions}&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="p">|</span> jq <span class="s1">&#39;.[] | select(.phase==&#34;runtime&#34;)&#39;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;network&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;target&#34;</span><span class="p">:</span> <span class="s2">&#34;example.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;action&#34;</span><span class="p">:</span> <span class="s2">&#34;deny&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;assuranceLevel&#34;</span><span class="p">:</span> <span class="s2">&#34;observed&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="err">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>(The reporter batches; if the output is empty, wait a moment and re-run. The <code>select</code>
skips <code>merge</code>-phase entries — control-plane records of how your policies were
resolved — and keeps what the proxy <em>observed</em>.)</p>
<p><code>observed</code> = reported by the proxy under its own identity. The agent can&rsquo;t forge or
suppress it; anything the agent submits is stamped <code>self-reported</code> instead.
(<a href="/docs/concepts/core-concepts/#evidence-assurance">Why.</a>)</p>
<p>The block itself, at the proxy:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl logs first-session-egress -c envoy <span class="p">|</span> grep example.com   <span class="c1"># → 403</span>
</span></span></code></pre></div>
  </div>
</details>

<details class="docs-details">
  <summary>7 · Flip the rule to audit-only</summary>
  <div class="docs-details-body">
    <p>One field turns enforcement into rehearsal — traffic flows, the denial is recorded as
<code>dry-run</code>. Flip the policy, then run a <strong>second</strong> session under it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl patch agentpolicy deny-example --type merge -p <span class="s1">&#39;{&#34;spec&#34;:{&#34;mode&#34;:&#34;audit-only&#34;}}&#39;</span>
</span></span><span class="line"><span class="cl">sed <span class="s1">&#39;s/name: first-session/name: first-session-audit/&#39;</span> session.yaml &gt; session-audit.yaml
</span></span><span class="line"><span class="cl">kubectl apply -f session-audit.yaml
</span></span><span class="line"><span class="cl">kubectl get agentsessions -w
</span></span></code></pre></div><p>Same agent, same rule: this time the wget goes through. Read the new record:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl get agentsession first-session-audit -o <span class="nv">jsonpath</span><span class="o">=</span><span class="s1">&#39;{.status.policyDecisions}&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="p">|</span> jq <span class="s1">&#39;.[] | select(.phase==&#34;runtime&#34;)&#39;</span>
</span></span></code></pre></div><p><code>&quot;action&quot;: &quot;dry-run&quot;</code> — still <code>observed</code>. And <code>first-session</code> still holds its <code>deny</code>:
re-run step 6 and compare them side by side. Mode changed what <em>happened</em>, never what
was <em>seen</em>.</p>
<p>A second session — not a delete-and-rerun — on purpose: the session object <strong>is</strong> the
audit record, and today the evidence lives only in its <code>status</code>. Delete the session
and the record is gone. Rerun by creating a new session; keep the old one.</p>

  </div>
</details>

<details class="docs-details">
  <summary>8 · Clean up</summary>
  <div class="docs-details-body">
    <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl delete -f session.yaml -f session-audit.yaml -f policy.yaml -f runtimeprofile.yaml
</span></span><span class="line"><span class="cl">kubectl delete -k config/default
</span></span></code></pre></div><p>(<code>config/default</code> includes the CRDs, so the second command removes everything —
including any sessions still on the cluster, and their evidence with them.)</p>

  </div>
</details>

<p><strong>What you just saw:</strong> governance from outside the agent&rsquo;s trust domain (stock
busybox, zero cooperation) · enforcement verified against your CNI, not assumed ·
a block that really happened, with a record the agent couldn&rsquo;t forge.</p>
<p>Next: the <a href="/docs/getting-started/demo/">demo</a> adds a live bypass attempt;
<a href="/docs/concepts/core-concepts/">core concepts</a> explains the objects you just used.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
