Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ServiceDefinition L0 validation (R-GITOPS-02)
Validates the shape of each catalog/ ServiceDefinition against the canonical
schema and invariants in the read-only spec docs/13-service-catalog.md (with
auth from docs/15, egress from docs/03). Runs in CI without a cluster.
Why kyverno-json (not the resource CLI)
A ServiceDefinition is arbitrary YAML — its own kind: field means
container | vm, not a Kubernetes Kind — so it cannot be validated by
kyverno apply/kyverno test (which expect Kubernetes resources). Per
ADR-0011 the Kyverno-ecosystem tool for arbitrary YAML/JSON is kyverno-json.
Invariants enforced (validate-servicedefinition.yaml)
nameis a DNS-1123 label (→<name>.home.keithjackson.dev).kind∈ {container,vm}; container ⇒source.image, vm ⇒source.vmTemplate.exposure∈ {internal,public}.egress∈ {internet,vpn}.auth.mode∈ {oidc,forward-auth,native,none}.publicexposure ⇒auth.mode≠none(no unauthenticated public UI, docs/15).- each
dependencies[]hasto,port∈ 1–65535,protocol∈ {tcp,udp}. - each
storage[].class∈ {longhorn,bulk}.
Fixtures
payloads/valid-*.yaml must PASS; payloads/invalid-*.yaml must FAIL — one failure
reason each (bad egress, public+none auth, missing image, bad dependency).
Run (CI entrypoint)
# Valid payloads: scan must exit 0
kyverno-json scan \
--policy validate-servicedefinition.yaml \
--payload payloads/valid-plex.yaml \
--payload payloads/valid-sonarr.yaml
# Invalid payloads: each scan must exit NON-zero (loop asserts failure)
for f in payloads/invalid-*.yaml; do
if kyverno-json scan --policy validate-servicedefinition.yaml --payload "$f"; then
echo "FAIL: expected $f to be rejected"; exit 1
fi
done
The scripts/run-l0.sh wrapper (see ../README.md) runs both halves and is what CI
invokes.
Caveat (escalated in the T-0.5 report)
kyverno-json is pre-1.0; its assertion syntax evolves. The invariants above are
the normative content. The CI agent must pin an exact kyverno-json version and
confirm the check: expressions parse under it; adjust syntax (never the invariants)
if the pinned release differs. The overlapping JSON Schema from WS-GITOPS (T-0.3) is
the complementary structural contract.