validate
cotctl validate checks your YAML before you deploy it. Getting into the habit of validating first is one of the highest-value things you can do as a partner: it catches mistakes on your machine, in seconds, instead of as a half-applied change in a customer's environment.
There are three things you might want to validate, and validate has a mode for each:
| Mode | Flag | Network | What it's for |
|---|---|---|---|
| File | -f <file> | Offline | Check a single Survey YAML file |
| Directory | --dir <path> | Offline | Cross-check a whole folder of resources before apply --dir |
| Workflow | --workflow <nameCode> | Online | Run the production-readiness checklist against a live workflow |
File mode — one survey, offline
The quickest check. Validates a single Survey YAML against the schema, with no API call:
cotctl validate -f my-survey.yaml
✓ my-survey.yaml is valid
If something's wrong, it tells you what and where:
✗ my-survey.yaml has validation errors:
- code: code must start with a lowercase letter and contain only lowercase letters, numbers, and underscores
Under the hood, three layers of checking run:
| Layer | What it checks | How to skip |
|---|---|---|
| Structure (Zod) | Types, required fields, enums | Always on |
| Semantic | function run() in exec hooks, buttons in the wrong stage, deprecated fields | --skip-semantic-validation |
| Remote | Identifier uniqueness across the company, that referenced entities exist | Needs --remote + -c <profile> |
The first two are offline. Remote checks reach the API, so they require a profile:
cotctl validate -f my-survey.yaml --remote -c acme
Directory mode — a whole folder, offline
This is the one you'll use most when working with scaffolded workflows. It validates every YAML file in a folder and checks that they reference each other correctly — all offline. Run it right before apply --dir:
cotctl validate --dir ordenes-compra/
It runs two families of checks. Schema checks, per file:
| ID | Check |
|---|---|
| S1 | File parses as valid YAML |
| S2 | kind is present and recognized |
| S3 | Document validates against the schema for its kind |
And cross-reference checks, across files — this is what catches a property pointing at a property type that doesn't exist:
| ID | Severity | Check |
|---|---|---|
| X1 | warn | Permission strings (name:action) are defined as AccessRoles |
| X2 | fail | Property.propertyType references an existing PropertyType |
| X3 | fail | Workflow state machine propertyType references resolve |
| X4 | fail | Workflow states[].property references an existing Property |
| X5 | fail | The state machine initialState references an existing Property |
| X6 | warn | Workflow permissions are defined as AccessRoles |
A clean run ends with a clear verdict:
Results: 11 PASS, 0 WARN, 0 FAIL — ready to apply
Add --json if you want to consume the result in a script.
Workflow mode — production readiness, online
Once a workflow is live, this mode runs the Marcha Blanca (go-live) checklist against it. It's an online check, so it needs a profile:
cotctl validate --workflow ordenes_compra -c prod
The checklist is organized in three sections, and you can run just one with --section:
- Nomenclature (
nomenclature) — naming conventions for codes, forms, properties, and permissions. - Permissions (
permissions) — that a Manager role exists with all flow permissions, wired into the linked forms. - Configuration (
configuration) — technical rules, like control fields being read-only and an error state existing.
# only the naming checks
cotctl validate --workflow ordenes_compra --section nomenclature -c prod
Results: 13 PASS, 1 WARN, 0 FAIL — production ready
Checks are graded WARN (a recommendation) or FAIL (a real problem). The command exits 0 when everything passes or only warns, and 1 when at least one check fails — which is exactly what you want as a gate in a pipeline.
A couple of known limits. Deep JavaScript code-quality checks on exec hooks aren't implemented, and the error-state check (T3) looks for the _estado_error naming convention — if your implementation names its error state differently, expect a warning even when an error state exists.
See also
- apply — deploy your resources once validation passes
- scaffolding — generate a workflow skeleton to validate and apply