> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Validate

A [contract](https://www.walkeros.io/docs/getting-started/flow/contract.md) is the canonical definition of what your events should look like. Validation enforces that contract at runtime with an explicit transformer step, `@walkeros/transformer-validate`, the same way enrichment or decoding is a transformer step. The contract describes the shape; the transformer applies it.

## Where event shapes live[​](#where-event-shapes-live "Direct link to Where event shapes live")

Event shapes live in the top-level `contract` block of flow\.json (a sibling of `flows`), keyed by entity then action as JSON Schema, with `extend` inheritance and `*` wildcards. Reference any contract from a step with `$contract.<name>`.

```
{

  "version": 4,

  "contract": {

    "web": { "events": { "order": { "complete": { "properties": { "data": { "required": ["total", "currency"] } } } } } }

  }

}
```

See [Contract](https://www.walkeros.io/docs/getting-started/flow/contract.md) for the full shape, inheritance with `extend`, and wildcard merging.

## Enforce at runtime[​](#enforce-at-runtime "Direct link to Enforce at runtime")

Add a `@walkeros/transformer-validate` step and point its `contract` setting at the contract. The transformer reads the `{ ingest, event }` context and validates the canonical event.

```
{
  "version": 4,
  "contract": {
    "web": { "events": { "order": { "complete": { "properties": { "data": { "required": ["total", "currency"] } } } } } }
  },
  "flows": {
    "default": {
      "transformers": {
        "validate": {
          "package": "@walkeros/transformer-validate",
          "config": { "settings": {
            "contract": ["$contract.web"],
            "format": true,
            "mode": "strict",
            "output": { "isValid": "source.valid", "errors": "validation" }
          } },
          "next": "ga4"
        }
      }
    }
  }
}
```

### Settings[​](#settings "Direct link to Settings")

| Field       | Type                                  | Description                                                                                                                                                                                             |
| ----------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contract?` | `Array<$contract ref \| JSON Schema>` | Constraints. A `$contract.<name>` ref selects per `entity.action`; an inline schema applies to the whole event. All entries must pass (AND).                                                            |
| `format?`   | `boolean`                             | Also validate the canonical `WalkerOS.Event` structure. All fields are optional, so this checks shape and field types, not presence.                                                                    |
| `mode?`     | `'strict' \| 'pass'`                  | `strict` drops invalid events (stops the chain); `pass` (default) annotates and continues so a downstream route can act.                                                                                |
| `output?`   | `{ isValid?, errors? }`               | Split targets. `isValid` (default `source.valid`) writes the boolean verdict onto the event; `errors` (default `validation`) writes the issue list onto the ingest context. Empty string skips a write. |

The verdict travels with the event as analytics-grade data (`event.source.valid`). The issue list (`{ path, message }` entries) stays off the event, on the observer-visible ingest context, so it survives even a strict-mode drop.

## Filter unwanted events[​](#filter-unwanted-events "Direct link to Filter unwanted events")

Filtering is the same mechanism, not a separate setting. Author an inline schema that rejects the unwanted events and run `mode: "strict"`. For example, drop GTM lifecycle noise (`gtm.js`, `gtm.dom`) by rejecting any `name` matching `^gtm\.`:

```
"validate": {
  "package": "@walkeros/transformer-validate",
  "config": { "settings": {
    "contract": [{ "type": "object", "properties": { "name": { "not": { "pattern": "^gtm\\." } } } }],
    "mode": "strict"
  } }
}
```

## Design-time checks[​](#design-time-checks "Direct link to Design-time checks")

The CLI flow validator checks step examples (`destination.in`, `transformer.in`) against the resolved contract and reports violations before you deploy, so a sample event that breaks the contract is caught at authoring time.

```
walkeros validate flow.json
```

## Break it on purpose[​](#break-it-on-purpose "Direct link to Break it on purpose")

Contracts are easiest to trust after watching one fail. Take the contract above (it requires `total` and `currency` on `order complete` data) and give a step example an event that misses `currency`. The validator names the exact path and problem:

```
Validation Results:
  ⚠ destination.ga4.examples.purchase.in: Example violates contract: #/data: Instance does not have required property "currency".
    → Fix the example data to satisfy the contract schema.

Summary: 0 error(s), 1 warning(s)
```

Contract violations are warnings by default; add `--strict` to turn them into errors (exit code 1) and fail CI before a broken event shape ships. A tag manager drops the same broken field silently, in production.

## Next steps[​](#next-steps "Direct link to Next steps")

* **[Contract](https://www.walkeros.io/docs/getting-started/flow/contract.md)**: named, inheritable schemas referenced via `$contract`
* **[Validate transformer](https://www.walkeros.io/docs/transformers/validate.md)**: full settings reference and recipes
* **[Mapping](https://www.walkeros.io/docs/mapping.md)**: transform events between steps
