# In-cluster conformance Job (L2/L3) > **STATUS NOTE (2026-09-29) — read before trusting the "Phase 0" framing below.** > This document speaks as though no cluster exists and the platform is scaffolding. **A > three-node k3s cluster has existed for weeks** and Flux has been reconciling against it. > Gitea is live, the Actions runner `incluster-dind` is online, and `main` is a protected > branch. Where the text says "Phase 0", "stub", or "no cluster exists", read it as > describing a **live gap** rather than an expected stage — most importantly, L2/L3 > conformance still does not run in CI (`vars.CLUSTER_AVAILABLE` is unset), which is a real > coverage hole, not a phase. > > This mismatch is not cosmetic. A month of "the gate enforces this" claims rested on > documentation rather than measurement, and `main` was unprotected with zero runners > registered the whole time. **Query the live API before asserting platform state.** Per **ADR-0011** and **docs/14 "Where each layer runs"**: L0/L1 run in CI without a cluster, but **L2 behavioral and L3 fault-injection run as an in-cluster Chainsaw Job** on the dev/test cluster that **CI triggers and waits for**. CI holds **no** cluster credentials — the Job's own scoped ServiceAccount does (R-SEC-02). ## Files - `rbac.yaml` — the `conformance` namespace, the `conformance-runner` ServiceAccount, and a **least-privilege ClusterRole skeleton**. Rules start **empty** and are added — each commented with the test/requirement that needs it — only as the matching fault-injection test lands. This is a **privileged test identity**: never reused by workloads, its own audit item. - `chainsaw-job.yaml` — the Job skeleton. Single entrypoint `./run.sh`; CI sets `args` to `--requirements ` (merge gate) or `--layer all --strict-coverage` (phase exit). Image pinned to `versions.env` `CHAINSAW_IMAGE`. ## Flow 1. CI (Gitea Actions, delivered in T-6.1b) creates a Job from `chainsaw-job.yaml` (via a trigger with narrow rights: create Job + read its logs/status — *not* a broad kubeconfig). 2. The Job clones/loads the impl repo at the commit under test into `/workspace` and runs `./run.sh` under `conformance-runner`. 3. `run.sh` runs Chainsaw over the selected tests and writes `report.junit.xml` + `coverage/` to the results volume (`/workspace/conformance/_artifacts`). 4. CI collects those artifacts (results volume or the terminating log stream, which echoes their paths) and enforces the merge / phase-exit gate on them. ## Phase 0 No cluster exists, so nothing here is applied yet. These manifests are reconciled by Flux from Phase 1+ and first exercised when L2/L3 can run (T-3.0 onward). In Phase 0 the same `run.sh` runs in CI's no-cluster stage and emits a **skipped** JUnit + the coverage report.