UseArazzo Validator

In development

Every violation against the Arazzo specification, with the location that caused it.

@usearazzo/validator is a validator and linter for Arazzo Specification documents. It performs semantic validation and semantic linting, with JSON Schema validation available opt-in, and returns diagnostics compatible with the Language Server Protocol and VS Code.

Not yet published. There is no @usearazzo/validator package on npm today. It is developed inside the arazzo-toolkit monorepo and will be installable once its API stabilizes. The API described below is the library as it exists there, and it may change without notice. Follow Discussions to hear when it ships.

Supported versions:

  • ✓ Arazzo 1.0.0, 1.0.1

Availability

For now the Validator runs from a checkout of the arazzo-toolkit monorepo, where it is developed. It is not on npm yet, so there is no install command to give you; once it publishes, that becomes a single line.

Validating Arazzo Documents

Two functions cover every input shape: validateURI for file paths and URLs, and the lower-level validate for an in-memory TextDocument.

From a file

import { validateURI, DiagnosticSeverity } from '@usearazzo/validator';

const diagnostics = await validateURI('/path/to/arazzo.yaml');

From a URL

import { validateURI } from '@usearazzo/validator';

const diagnostics = await validateURI('https://example.com/arazzo.yaml');

From an in-memory document

When you already have document content in memory, use validate with createTextDocument:

import { validate, createTextDocument } from '@usearazzo/validator';

const content = `
arazzo: '1.0.1'
info:
  title: My Workflow
  version: '1.0.0'
sourceDescriptions:
  - name: myApi
    type: openapi
    url: https://example.com/openapi.json
workflows:
  - workflowId: myWorkflow
    steps:
      - stepId: step1
        operationId: myApi.getUsers
`;

const textDocument = createTextDocument('file:///path/to/arazzo.yaml', content);
const diagnostics = await validate(textDocument);

Every diagnostic is LSP-compatible, so it carries a precise range, a severity, and a numeric code, the same shape a VS Code extension would render inline. Illustrative shape, not the literal output of a specific document:

Validation Options

Customizing language service context

Both functions accept an optional context parameter:

import { validateURI } from '@usearazzo/validator';

const diagnostics = await validateURI('/path/to/arazzo.yaml', {
  validationContext: {
    jsonSchemaValidation: true,   // Opt in to JSON Schema validation (default: false)
    semanticValidation: true,     // Perform semantic validation (default: true)
    referenceValidation: true,    // Validate references (default: true)
    semanticLinting: true,        // Apply linting rules (default: true)
    betterAjvErrors: true,        // Use improved error messages (default: true)
  },
  parseContext: {
    fileAllowList: ['*'],         // Glob patterns for allowed files (default: ['*'])
    arazzo: {
      sourceDescriptionsResolution: true, // Resolve source descriptions (default: true)
    },
  },
});

jsonSchemaValidation is off by default. Turning it on adds structural checks from the Arazzo JSON Schema, which mostly catch malformed Reusable Object references. The cost is duplicate output, because the linting rules already report many of the same problems.

referenceValidation checks that local $ref pointers in workflow.inputs and components.inputs point at something that exists.

Relative sourceDescriptions[].url entries need a baseURI to resolve against. validateURI works one out from the file location. validate cannot, because its TextDocument may only exist in memory, so pass baseURI yourself.

Customizing URI resolution

validateURI canonicalizes its input into an absolute URI before anything else, so a relative path, an absolute path, and any legal form of a file: URI all land on the same location. That is what makes relative references inside the document, such as sourceDescriptions[].url: ./openapi.yaml, resolve the same way no matter how you named the file.

To fetch the document it reuses the file and HTTP resolvers from @usearazzo/parser, which sets the HTTP resolver to a 15 second timeout, 5 redirects, and no credentials. A third parameter overrides that. Note that resolverOpts is not a fixed set of options: its entries are merged onto the resolver instance, so the keys worth setting are the resolver's own properties, which for the HTTP resolver are timeout, redirects, withCredentials, and cache.

import { validateURI } from '@usearazzo/validator';

const diagnostics = await validateURI('https://example.com/arazzo.yaml', {}, {
  resolverOpts: {
    timeout: 10000, // HTTP timeout in milliseconds
  },
});

Security Considerations

Two allow lists gate file access, at different layers. The resolver behind validateURI only reads paths matching its patterns, which by default admit local .json, .yaml, and .yml files and nothing else. parseContext.fileAllowList gates what the language service may open while it resolves source descriptions during semantic linting, and defaults to ['*'], which matches anything. sourceDescriptionsResolution is also on by default, so external documents named in the Arazzo document are fetched and parsed.

When validating untrusted documents, restrict file access:

const diagnostics = await validateURI('/path/to/arazzo.yaml', {
  parseContext: {
    fileAllowList: [],  // Disable file access
    arazzo: {
      sourceDescriptionsResolution: false, // Disable source description resolution
    },
  },
});

Working with Diagnostics

Both validation functions return an array of Diagnostic objects compatible with VS Code and the Language Server Protocol.

import { validateURI, DiagnosticSeverity } from '@usearazzo/validator';

const diagnostics = await validateURI('/path/to/arazzo.yaml');
const errors = diagnostics.filter((d) => d.severity === DiagnosticSeverity.Error);
const warnings = diagnostics.filter((d) => d.severity === DiagnosticSeverity.Warning);
const isValid = errors.length === 0;

Rest of the Toolkit

Runner

Executes the workflows you validate here, interpreting the same Arazzo semantics.

Explore Runner

CLI

Will put this library behind a command, so validation runs from a terminal instead of your own code.

Explore CLI

Under the hood, the Validator uses @usearazzo/parser to load and resolve referenced files.

Frequently Asked Questions

Can I install the Validator today?

Not from npm. @usearazzo/validator has not been published yet and is under heavy development inside the arazzo-toolkit monorepo. It will publish once its API stabilizes.

Is the Validator free?

Yes. @usearazzo/validator is free, open-source, and licensed under Apache 2.0, and it will stay that way once published.

What does it check?

Semantic validation against the Arazzo specification, semantic linting, and reference validation, which checks that local $ref pointers inside workflow.inputs and components.inputs resolve to a target that exists. JSON Schema (AJV) validation is available on top of that, opt-in.

Which Arazzo versions does it support?

Arazzo 1.0.0 and 1.0.1. Arazzo 1.1.0 is not yet supported.

Is it safe to run on documents I don't fully trust?

By default the validator can read any local file and will fetch external source descriptions referenced by the document. When validating untrusted input, set fileAllowList: [] and sourceDescriptionsResolution: false to disable both.