# How Archify's Schema System Enforces Strict Validation: JSON-Schema, Ajv, and Fail-Closed Design

> Discover how Archify's schema system enforces strict validation using JSON-Schema, Ajv, and a fail-closed design to prevent rendering errors. Learn more!

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: internals
- Published: 2026-09-10

---

**Archify enforces strict validation through a multi-layered pipeline that combines static JSON-Schema definitions with `additionalProperties: false`, compile-time Ajv validator generation, and runtime fail-closed enforcement that halts rendering on any schema violation.**

Archify treats every diagram as a formally-defined contract that must conform to a strict structural specification. The system guarantees data integrity by combining **static JSON-Schema definitions** with **runtime validation** powered by Ajv (Another JSON Validator), ensuring that malformed inputs never reach the rendering engine. This deep dive examines the technical implementation of Archify's schema enforcement mechanisms in the `tt-a1i/archify` repository.

## Static Schema Definitions with `additionalProperties: false`

Archify's strictness begins at the schema definition level. Each renderer—whether for workflow, sequence, dataflow, lifecycle, or architecture diagrams—maintains its own top-level schema file (`*.schema.json`) that defines the exact shape of valid input.

All schemas import a shared set of definitions from [`common.schema.json`](https://github.com/tt-a1i/archify/blob/main/common.schema.json) and mandate three core fields: `schema_version`, `diagram_type`, and `meta`, plus renderer-specific structural arrays (such as `nodes`, `edges`, and `lanes`). Crucially, every object level in these schemas sets **`additionalProperties: false`**, which rejects any unexpected fields outright rather than silently ignoring them.

According to the schema documentation in [`archify/schemas/README.md`](https://github.com/tt-a1i/archify/blob/main/archify/schemas/README.md) (lines 17‑20), this configuration ensures that a document containing an undefined property—such as an extra `colour` field on a node—fails validation immediately, preventing typo-tolerance that could mask data errors.

## Schema Version Pinning and Contract Stability

Strict validation requires explicit version contracts. Four of the five diagram types lock their `schema_version` field to `1`, while the workflow renderer supports both `v1` and `v2`. The version tag is mandatory and explicit in every document; a diagram authored for `v1` will never be silently reinterpreted as a newer version.

This pinning strategy, documented in [`archify/schemas/README.md`](https://github.com/tt-a1i/archify/blob/main/archify/schemas/README.md) (lines 10‑15), guarantees backward compatibility and prevents accidental schema drift. When the workflow renderer encounters `"schema_version": 1`, it applies exactly the v1 validation rules, ensuring deterministic behavior across executions.

## Compile-Time Validator Generation with Strict Ajv

Archify moves validation overhead from runtime to build time through **standalone validator compilation**. The script `archify/scripts/generate-validators.mjs` processes each JSON-Schema file using Ajv's **draft-2020-12 standalone generator** with the options `strict: true` and `allErrors: true`.

This compilation step produces zero-dependency JavaScript validators that are checked into the repository at `archify/renderers/shared/generated-validators.mjs`. By pre-compiling the validators, Archify eliminates Ajv as a runtime dependency for end users while preserving comprehensive error reporting. The `strict: true` option ensures that the schemas themselves are strictly validated during compilation, catching issues like invalid schema keywords before they reach production.

## Runtime Validation Layer: Fail-Closed Enforcement

When a renderer initializes, `archify/renderers/shared/validator.mjs` selects the appropriate pre-compiled validator from the generated module and executes it against the incoming JSON-IR **before any layout logic executes**. This represents a **fail-closed** security model: if validation reports any error, the renderer aborts with a non-zero exit code and prints a path-prefixed diagnostic.

For example, consider a workflow diagram that violates the `additionalProperties: false` constraint:

```javascript
// ❌ Invalid: extra property `colour` on node
const badWorkflow = {
  schema_version: 1,
  diagram_type: "workflow",
  meta: { title: "Bad Flow" },
  nodes: [{ id: "router", type: "router", colour: "red" }],
  edges: [],
  lanes: []
};

```

Running `archify render workflow` produces an immediate halt with this error:

```text
workflow schema validation failed:
/nodes/0 (id/label: "router") must NOT have additional properties {"additionalProperty":"colour"}

```

The renderer never attempts layout or rendering for invalid documents, ensuring that output artifacts always match the expected schema.

## Post-Schema Cross-Collection Checks

After the JSON-Schema validation passes, Archify runs additional semantic checks that JSON-Schema alone cannot express. These include detecting **duplicate `id` values**, verifying that `focus` IDs actually exist in the document, and ensuring relationship IDs reference valid nodes.

These cross-collection validations are also fail-closed. As noted in [`archify/schemas/README.md`](https://github.com/tt-a1i/archify/blob/main/archify/schemas/README.md) (lines 61‑64), they reinforce strictness beyond pure structural validation, catching logical inconsistencies that would otherwise produce incorrect diagrams.

## Degraded Mode and Optional Validation Skipping

In environments where Ajv cannot be installed—such as minimal HTML exports—Archify enters a **degraded mode**. The renderer emits a warning and **skips schema validation** while continuing to perform layout checks. This keeps the viewer functional but makes strictness optional only when the validator is unavailable, as implied in the workflow renderer documentation.

```javascript
// ✅ Valid minimal workflow (schema_version 1)
const goodWorkflow = {
  schema_version: 1,
  diagram_type: "workflow",
  meta: { title: "Simple Flow" },
  nodes: [{ id: "start", type: "entry" }],
  edges: [{ from: "start", to: "end" }],
  lanes: []
};

```

## Summary

- **Strict Schema Definitions**: Every object uses `additionalProperties: false` to reject undefined fields immediately.
- **Version Pinning**: Explicit `schema_version` fields prevent silent interpretation of documents against newer schemas.
- **Pre-compiled Validators**: `scripts/generate-validators.mjs` uses Ajv with `strict: true` to generate standalone validators checked into `renderers/shared/generated-validators.mjs`.
- **Fail-Closed Runtime**: `renderers/shared/validator.mjs` halts execution with detailed path-prefixed errors before layout begins.
- **Semantic Validation**: Post-schema checks enforce referential integrity (unique IDs, valid focus targets) beyond structural validation.
- **Graceful Degradation**: Validation skips only when Ajv is unavailable, preserving functionality without compromising strictness in standard environments.

## Frequently Asked Questions

### What happens if I add an extra field to a node in Archify?

Archify rejects the document immediately. Because every schema level sets `additionalProperties: false`, any unexpected property—such as a typo like `lable` instead of `label`—triggers a validation error in `renderers/shared/validator.mjs` that halts rendering and reports the specific path and offending property.

### Why does Archify pre-compile validators instead of using Ajv at runtime?

Pre-compiling validators via `scripts/generate-validators.mjs` removes Ajv as a runtime dependency, resulting in faster startup times and zero-dependency deployment. The generated code in `renderers/shared/generated-validators.mjs` contains all validation logic inline while maintaining the same `strict: true` and `allErrors: true` behavior as the original Ajv configuration.

### How does Archify handle schema versions for workflow diagrams?

While most diagram types lock to `schema_version: 1`, workflow diagrams support both `v1` and `v2`. The version is explicitly declared in the document's `schema_version` field, and the validator selects the appropriate pre-compiled schema from `generated-validators.mjs` based on this value, ensuring that v1 documents are never validated against v2 rules.

### What checks run after JSON-Schema validation completes?

After structural validation passes, Archify performs cross-collection checks for logical consistency. These include verifying that all `id` values are unique, that `focus` references point to existing nodes, and that relationship IDs are valid. These checks run in the rendering pipeline after `validator.mjs` completes and also follow fail-closed behavior.