A validation pipeline is an ordered list of checks that runs against a request's validation environment. The output becomes review evidence: pass, warning, fail, findings, and downloadable artifacts.
Fast path
Use the default pipeline first. Add policy checks in YAML when you need organization rules. Reach for custom scripts or containers only when the built-in checks are not enough.
Mental model
Reviewer
Runs a pipeline from a request and reads the evidence before approving.
Admin
Creates and edits YAML pipeline definitions, enables defaults, and controls approval gates.
Integrator
Creates pipelines and starts validation runs through the JSON API.
Contributor
Adds new built-in step types or scanner integrations to Foyre itself.
Prerequisites
- A Foyre instance with a connected host cluster
- A request with a ready validation environment and workload deployed into it
reviewer,architect, oradminrole to run pipelinesadminrole to create, edit, enable, delete, or set default pipelines- A bearer token if you are using the API examples
1. Run a pipeline as a reviewer
Open a submitted request that has a ready validation environment. In the Validation pipeline section, choose a pipeline and click Run validation pipeline.
Expected result
Validation Pipeline: Default AI Workload Validation
Status: Failed
Checks: 1 passed, 1 warning, 1 failed
Approval Impact: Blocked
Expand each step to read the summary, findings, recommendations, timestamps, and evidence artifacts.
2. Create a pipeline as an admin
Go to Administration → Validation pipelines → New pipeline. Paste this YAML, validate it, and create the pipeline.
apiVersion: foyre.ai/v1alpha1
kind: ValidationPipeline
metadata:
name: default-ai-workload-validation
displayName: Default AI Workload Validation
description: Inventory, Kubernetes security, image scanning, and policy checks.
spec:
failurePolicy: warn
steps:
- name: workload-inventory
type: builtin.workload_inventory
displayName: Workload Inventory
required: true
failurePolicy: warn
timeoutSeconds: 120
config:
includeNamespaces: ["*"]
excludeNamespaces: [kube-system]
- name: kubernetes-security
type: builtin.kubernetes_security
displayName: Kubernetes Security Review
required: true
failurePolicy: block
dependsOn: [workload-inventory]
timeoutSeconds: 120
config:
denyPrivilegedContainers: true
warnIfRunAsRoot: true
warnIfMissingResourceLimits: true
warnIfHostPathMounts: true
warnIfHostNetwork: true
- name: image-scan
type: builtin.image_scan
displayName: Container Image Scan
required: true
failurePolicy: block
dependsOn: [workload-inventory]
timeoutSeconds: 900
config:
scanner: trivy
failOnCritical: true
warnOnHigh: true
ignoreUnfixed: false
- name: org-policy
type: builtin.policy
displayName: Organization Policy
required: true
failurePolicy: block
dependsOn: [workload-inventory]
timeoutSeconds: 120
config:
checks:
no_privileged_containers: { severity: high }
require_resource_limits: { severity: low }
deny_latest_tag: { severity: medium }
allowed_registries:
severity: high
registries: ["registry.example.com", "ghcr.io/acme"]
required_labels:
severity: low
labels: ["app.kubernetes.io/owner"]
banned_capabilities:
severity: high
capabilities: ["SYS_ADMIN", "NET_ADMIN", "ALL"]
host_path_mounts: { severity: high }
After creating it, use row actions to enable it and optionally set it as the default pipeline. Each save increments the pipeline version. Existing runs keep the definition snapshot they used.
3. Add custom checks when policy YAML is not enough
Custom steps run inside the validation environment. Inputs from upstream steps are mounted at
/foyre/input. Anything written to
/foyre/output becomes evidence.
Inline script
- name: egress-check
type: custom.script
displayName: Egress Check
failurePolicy: warn
dependsOn: [workload-inventory]
timeoutSeconds: 300
config:
interpreter: bash
script: |
set -euo pipefail
jq '.workloads[]?.images[]?' /foyre/input/workload-inventory.json > /foyre/output/images.txt
echo '{"status":"passed","severity":"none","summary":"Image list captured.","findings":[]}' > /foyre/output/result.json
Bring your own container
- name: company-policy
type: custom.kubernetes_job
displayName: Company Policy Check
failurePolicy: block
dependsOn: [workload-inventory]
timeoutSeconds: 300
config:
image: registry.example.com/security/company-ai-checker:latest
command: ["/app/check"]
args: ["--input", "/foyre/input/workload-inventory.json"]
env:
POLICY_MODE: strict
Chart settings
Inline scripts and uploaded output artifacts require the validation runner image and an ingest URL reachable from the validation environment. Without that wiring, custom steps can still run in log-only mode.
4. Configure approval gates
Under Administration → Validation pipelines → Approval policy, set how validation affects approval.
5. Create and run pipelines through the API
Set your base URL and bearer token:
export BASE=http://localhost:8080
export TOKEN=<your-bearer-token>
export REQUEST_ID=<request-id>
Validate pipeline YAML before saving it:
python - <<'PY' > pipeline.json
import json
from pathlib import Path
definition = Path("pipeline.yaml").read_text()
print(json.dumps({"definition_yaml": definition, "enabled": True, "is_default": False}))
PY
curl -X POST "$BASE/api/validation/pipelines/validate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d @pipeline.json
Create the pipeline, set it as default if needed, then start a run:
curl -X POST "$BASE/api/validation/pipelines" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d @pipeline.json
curl -X POST "$BASE/api/requests/$REQUEST_ID/validation-runs" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"reason":"Pre-production validation"}'
Poll the run and download evidence artifacts:
curl -H "Authorization: Bearer $TOKEN" \
"$BASE/api/requests/$REQUEST_ID/validation-runs"
export RUN_ID=<run-id>
curl -H "Authorization: Bearer $TOKEN" \
"$BASE/api/validation-runs/$RUN_ID"
curl -H "Authorization: Bearer $TOKEN" \
"$BASE/api/validation-runs/$RUN_ID/artifacts"
export ARTIFACT_ID=<artifact-id>
curl -H "Authorization: Bearer $TOKEN" \
"$BASE/api/validation-artifacts/$ARTIFACT_ID/download" \
-o evidence.json
6. Add a new built-in step as a contributor
Most teams should use builtin.policy,
custom.script, or
custom.kubernetes_job. Add a native executor only
when the check should ship as part of Foyre.
# backend/app/domain/validation_steps.py
"builtin.network_egress": StepTypeSpec(
type="builtin.network_egress",
display_name="Network Egress Review",
description="Inspect workloads for external network egress.",
builtin=True,
)
# backend/app/validation/executors/network_egress.py
from app.domain.enums import ValidationSeverity, ValidationStepStatus
from app.validation.types import ArtifactDraft, StepContext, StepOutcome
def run(ctx: StepContext) -> StepOutcome:
findings = []
return StepOutcome(
status=ValidationStepStatus.warning if findings else ValidationStepStatus.passed,
severity=ValidationSeverity.medium if findings else ValidationSeverity.none,
summary=f"{len(findings)} network egress finding(s).",
findings=findings,
details={"checked": True},
artifacts=[
ArtifactDraft(
name="network-egress.json",
artifact_type="json",
content=b'{"findings":[]}',
content_type="application/json",
)
],
)
# backend/app/validation/executors/__init__.py
from app.validation.executors.network_egress import run as network_egress_run
_REGISTRY = {
"builtin.network_egress": network_egress_run,
}
Troubleshooting
The run button is missing
Confirm the user has the reviewer,
architect, or
admin role.
The run will not start
The request needs a ready validation environment. Create the isolated cluster, deploy the workload, and then run the pipeline.
The pipeline YAML is rejected
Check apiVersion,
kind, unique step names, supported step
types, and dependency names.
Approval is blocked
Fix the workload and rerun validation, or use an override with a recorded reason if policy allows it.
What you should have now
- A working model for who runs, configures, automates, and extends validation pipelines
- A copyable pipeline YAML definition with inventory, security, image scan, and policy checks
- API commands for validating definitions, creating pipelines, starting runs, and downloading evidence
- Starting points for custom scripts, custom containers, and native built-in step development