Use when the user wants validation to be enforced (not just advisory) on ConfigHub Units, is setting up a new Space and wants policy to apply automatically, asks about ApplyGates, says "block bad config from being deployed", "wire up schema validation", "enforce a policy", "require approval", or needs to diagnose why a Unit is blocked from applying. This skill installs the platform-Space + Filter + TriggerFilterID pattern — centralized Triggers that run on every Mutation and attach ApplyGates when validation fails. Do not load for: running validators one-off without installing them (use cub-mutate with vet-* functions instead), or for authoring the YAML itself.
92
92%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Make validation enforced, not advisory. Without Triggers, vet-* functions are suggestions; with Triggers, they block the apply path.
cub function vet vet-* calls to automatic enforcement.cub-mutate or a direct cub function vet vet-schemas …).config-as-data).cub-mutate.cub organization list succeeds (proves a valid token; cub context get / cub info / cub version don't require one).platform Space (or whichever Space will hold Triggers) and on the target application Spaces.platform Space, or do they already have a different convention? Default recommendation is platform.Best practice: one dedicated Space holds Triggers. A Filter selects them. Application Spaces reference that Filter via TriggerFilterID. This means you define policy once; every Space that uses the Filter inherits it.
# 1. Platform Space.
cub space create platform \
--change-desc "Create platform space to hold org-wide Triggers. User prompt: <verbatim>. Clarifications: <condensed>"
# 2. Baseline vet-* Triggers on Mutation.
for t in vet-schemas vet-placeholders vet-format vet-merge-keys vet-immutable; do
cub trigger create --space platform -o json "$t" Mutation Kubernetes/YAML "$t"
done
# 3. Filter selecting those Triggers.
cub filter create --space platform -o json standard-vets Trigger \
--where-field "Space.Slug = 'platform' AND FunctionName LIKE 'vet-%'"Verify flag spellings with CONFIGHUB_AGENT=1 cub space create --help, cub trigger create --help, cub filter create --help — flag names evolve across cub versions.
# New Space using the filter.
cub space create myapp-prod --trigger-filter platform/standard-vets --where-trigger "-"
# Existing Space — confirm flag spelling first.
cub space update myapp-prod --trigger-filter platform/standard-vets --where-trigger "-"Why --where-trigger "-": WhereTrigger and TriggerFilterID combine — both must match for a Trigger to apply to the Space. Every Space is created with a default WhereTrigger = SpaceID = '<this-space>' so Triggers defined in the Space itself apply by default. When you attach a cross-Space --trigger-filter (e.g., Triggers living in platform), that default still applies and nothing matches both predicates, so # Triggers = 0 in cub space get even though cub trigger list --filter <slug> resolves the filter correctly. To use the filter alone, clear the default with --where-trigger "-" (the sentinel; plain "" is indistinguishable from "flag not set"). Keep both predicates when you actually want the union's intersection — e.g., Space-local Triggers plus the platform baseline. Verify with cub space get -o json <space> — Triggers should be populated.
vet-cel evaluated once per resource (r aliases object). Return a bool for simple pass/fail; return a map with top-level snake_case keys passed, details, failed_attributes for diagnostics. Prefer failed_attributes (path-specific, with PascalCase entry keys ResourceName/ResourceType/Path/Value) over details when you can point at a specific attribute. Full shape and the Kubernetes CEL libraries (quantity(), url(), ip(), cidr(), regex(), format()) are documented in references/functions-catalog.md → "vet-cel — CEL validator with structured failures".
# Simple bool form.
cub trigger create --space platform -o json require-ha Mutation Kubernetes/YAML \
vet-cel 'r.kind != "Deployment" || r.spec.replicas >= 2'
# Path-specific failure — preferred over freeform details when you can name the attribute.
cub trigger create --space platform -o json require-ha Mutation Kubernetes/YAML \
vet-cel '
r.kind != "Deployment" || r.spec.replicas >= 2 ?
{"passed": true} :
{
"passed": false,
"failed_attributes": [{
"ResourceName": r.metadata.?namespace.orValue("") + "/" + r.metadata.name,
"ResourceType": r.apiVersion + "/" + r.kind,
"Path": "spec.replicas",
"Value": r.spec.replicas
}]
}'
# Disallow :latest.
cub trigger create --space platform -o json no-latest Mutation Kubernetes/YAML \
vet-cel 'r.kind != "Deployment" || !r.spec.template.spec.containers.exists(c, c.image.endsWith(":latest"))'See references/triggers-recipes.md for parameterized rules (--param=key=value → params.key) and quantity()-based numeric policy examples. If the Filter already matches (FunctionName LIKE 'vet-%' + platform scope), new Triggers propagate automatically.
cub trigger create --space platform -o json require-approval Mutation Kubernetes/YAML \
vet-approvedby 1cub unit get <slug> --space <space> — shows attached ApplyGates and which Trigger produced them.cub revision list <slug> --space <space> — find the revision that failed validation; the --change-desc should indicate what the user was trying to do.cub trigger get --space platform <trigger-slug> — see what the Trigger is checking.cub function set or cub unit update — the Mutation Triggers re-run automatically and release the gate if it passes.Never bypass a gate by dropping the Trigger, deleting the Filter, or editing gate state directly. If a rule is genuinely wrong, fix the Trigger in platform (with --change-desc recording why) so the whole fleet benefits.
cub space / trigger / filter / unit / revision — Unit-data mutations (cub unit update, cub function set, cub run) must pass --change-desc.--change-desc is a Unit-data-mutation flag only. It applies to cub unit update, cub function set, cub run, and cub unit update --patch. It does not apply to cub space create/update, cub trigger create/update/delete, cub filter create/update/delete, cub target create/update, or cub worker create/update — those entities aren't versioned configuration data and will reject the flag with unknown flag: --change-desc. The audit trail for Space/Trigger/Filter/Target/Worker operations is the entity's own history, not a per-call description.
When this skill's flow does cause a Unit-data mutation (e.g., cub unit update while resolving a blocked apply), compose the description as:
<summary: "Fix placeholder that was blocking vet-placeholders gate">
User prompt: <verbatim>
Clarifications: <condensed — e.g., "user confirmed the namespace value should be 'prod'">--help reports. Stop and re-check before guessing.cub trigger list --space platform — Triggers present.cub filter get --space platform standard-vets — Filter selects the expected Triggers.cub space get <app-space> — TriggerFilterID references the Filter.cub space get <space> --web — Space page shows attached Triggers/Filter.cub unit get <slug> --space <space> --web — shows gates on a Unit.cub trigger get --space platform <slug> --web — Trigger details.references/triggers-recipes.mdreferences/functions-catalog.md — which vet-* does what.references/cub-cli.md59ea831
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.